From: darkcoven Date: Mon, 1 Apr 2013 17:48:42 +0000 (+0200) Subject: Separated lib in two parts : low level and high level. X-Git-Url: https://git.sur5r.net/?p=ngadmin;a=commitdiff_plain;h=5c85d536dcad8cb319999ba7febb8b6c8abd73dd;ds=sidebyside Separated lib in two parts : low level and high level. --- diff --git a/.gitignore b/.gitignore index 777604b..5619528 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,9 @@ *.o *~ *.so +*.a admin admind lib/doc/ +raw/doc/ brouillon diff --git a/Makefile b/Makefile index 73ffad0..8af2203 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,14 @@ -all: lib libdoc cli +all: raw lib libdoc cli -lib: force +raw: force + @+$(MAKE) -C raw lib + + +lib: raw force @+$(MAKE) -C lib lib @@ -12,7 +16,7 @@ libdoc: force @+$(MAKE) -C lib libdoc -cli: force +cli: lib force @+$(MAKE) -C cli @@ -22,10 +26,12 @@ force: 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 diff --git a/lib/src/Makefile b/lib/src/Makefile index 786f827..b88451f 100644 --- a/lib/src/Makefile +++ b/lib/src/Makefile @@ -1,7 +1,7 @@ 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) diff --git a/lib/src/attr.c b/lib/src/attr.c deleted file mode 100644 index 3e12690..0000000 --- a/lib/src/attr.c +++ /dev/null @@ -1,465 +0,0 @@ - -#include - -#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; -} - - diff --git a/lib/src/attr.h b/lib/src/attr.h deleted file mode 100644 index e297b49..0000000 --- a/lib/src/attr.h +++ /dev/null @@ -1,132 +0,0 @@ - -#ifndef DEF_ATTR -#define DEF_ATTR - - -#include - -#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 - diff --git a/lib/src/list.c b/lib/src/list.c deleted file mode 100644 index 88a222b..0000000 --- a/lib/src/list.c +++ /dev/null @@ -1,406 +0,0 @@ - -#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; - -} - - - - diff --git a/lib/src/list.h b/lib/src/list.h deleted file mode 100644 index 3eaf2ba..0000000 --- a/lib/src/list.h +++ /dev/null @@ -1,71 +0,0 @@ - -#ifndef DEF_LIST -#define DEF_LIST - - -#include -#include -#include - -#ifdef MT_SAFE_LIST -#include -#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 - diff --git a/lib/src/protocol.c b/lib/src/protocol.c deleted file mode 100644 index de2c451..0000000 --- a/lib/src/protocol.c +++ /dev/null @@ -1,237 +0,0 @@ - -#include -#include -#include -#include -#include - -#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; -} - - diff --git a/lib/src/protocol.h b/lib/src/protocol.h deleted file mode 100644 index 3064fd4..0000000 --- a/lib/src/protocol.h +++ /dev/null @@ -1,157 +0,0 @@ - -#ifndef DEF_PROTOCOL -#define DEF_PROTOCOL - - -#include -#include - -#include - -#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 - diff --git a/raw/Makefile b/raw/Makefile new file mode 100644 index 0000000..9776fb3 --- /dev/null +++ b/raw/Makefile @@ -0,0 +1,21 @@ + + + +all: lib libdoc + + + +lib: + @+$(MAKE) -C src + +libdoc: + doxygen rawnsdp + + +clean: + @rm -rf doc + @+$(MAKE) -C src clean + +mrproper: clean + @+$(MAKE) -C src mrproper + diff --git a/raw/include/attr.h b/raw/include/attr.h new file mode 100644 index 0000000..e297b49 --- /dev/null +++ b/raw/include/attr.h @@ -0,0 +1,132 @@ + +#ifndef DEF_ATTR +#define DEF_ATTR + + +#include + +#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 + diff --git a/raw/include/list.h b/raw/include/list.h new file mode 100644 index 0000000..3eaf2ba --- /dev/null +++ b/raw/include/list.h @@ -0,0 +1,71 @@ + +#ifndef DEF_LIST +#define DEF_LIST + + +#include +#include +#include + +#ifdef MT_SAFE_LIST +#include +#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 + diff --git a/raw/include/protocol.h b/raw/include/protocol.h new file mode 100644 index 0000000..3064fd4 --- /dev/null +++ b/raw/include/protocol.h @@ -0,0 +1,157 @@ + +#ifndef DEF_PROTOCOL +#define DEF_PROTOCOL + + +#include +#include + +#include + +#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 + diff --git a/raw/src/Makefile b/raw/src/Makefile new file mode 100644 index 0000000..f9c2c6e --- /dev/null +++ b/raw/src/Makefile @@ -0,0 +1,31 @@ + +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) + + diff --git a/raw/src/attr.c b/raw/src/attr.c new file mode 100644 index 0000000..39f8f25 --- /dev/null +++ b/raw/src/attr.c @@ -0,0 +1,464 @@ + +#include + +#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; +} + + diff --git a/raw/src/list.c b/raw/src/list.c new file mode 100644 index 0000000..88a222b --- /dev/null +++ b/raw/src/list.c @@ -0,0 +1,406 @@ + +#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; + +} + + + + diff --git a/raw/src/protocol.c b/raw/src/protocol.c new file mode 100644 index 0000000..de2c451 --- /dev/null +++ b/raw/src/protocol.c @@ -0,0 +1,237 @@ + +#include +#include +#include +#include +#include + +#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; +} + +