]> git.sur5r.net Git - ngadmin/commitdiff
Raw: refactor attribute encoding and decoding
authordarkcoven <admin@darkcoven.tk>
Sun, 13 Oct 2013 15:06:09 +0000 (17:06 +0200)
committerdarkcoven <admin@darkcoven.tk>
Sun, 13 Oct 2013 16:52:32 +0000 (18:52 +0200)
23 files changed:
lib/src/Makefile.am
lib/src/bitrate.c
lib/src/firmware.c
lib/src/mirror.c
lib/src/netconf.c
lib/src/network.c
lib/src/ports.c
lib/src/qos.c
lib/src/session.c
lib/src/vlan.c
raw/include/nsdp/Makefile.am
raw/include/nsdp/attr.h
raw/include/nsdp/encoding.h [deleted file]
raw/include/nsdp/net.h
raw/include/nsdp/packet.h [new file with mode: 0644]
raw/include/nsdp/protocol.h
raw/src/Makefile.am
raw/src/attr.c
raw/src/encoding.c [deleted file]
raw/src/encoding_attr.c [deleted file]
raw/src/encoding_attr.h [deleted file]
raw/src/net.c
raw/src/packet.c [new file with mode: 0644]

index e80b991c644f68caed4f6a78a5722be644821708..e3817477f3cf25fb3054aceefeef6eaa7d2ef733 100644 (file)
@@ -3,6 +3,7 @@ pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = libngadmin.pc
 
 lib_LTLIBRARIES = libngadmin.la
+noinst_HEADERS = lib.h network.h
 
 libngadmin_la_SOURCES = network.c bitrate.c firmware.c libconf.c mirror.c misc.c \
                        netconf.c ports.c qos.c session.c vlan.c
index 50dfb769dd5dac7283476ca2d9c3db4b84bfbecd..82ec14c44b4c0a571dc7bf44522b761f2f244ee3 100644 (file)
@@ -65,11 +65,14 @@ int ngadmin_getStormFilterValues (struct ngadmin *nga, int *ports)
        struct attr *at;
        int ret = ERR_OK, port;
        struct attr_bitrate *sb;
+       struct swi_attr *sa;
        
        
        if (nga == NULL || ports == NULL)
                return ERR_INVARG;
-       else if (nga->current == NULL)
+       
+       sa = nga->current;
+       if (sa == NULL)
                return ERR_NOTLOG;
        
        
@@ -81,13 +84,14 @@ int ngadmin_getStormFilterValues (struct ngadmin *nga, int *ports)
        
        filterAttributes(attr, ATTR_STORM_BITRATE, ATTR_END);
        
-       for (port = 0; port < nga->current->ports; port++)
+       for (port = 0; port < sa->ports; port++)
                ports[port] = BITRATE_UNSPEC;
        
        for (ln = attr->first; ln != NULL; ln = ln->next) {
                at = ln->data;
                sb = at->data;
-               ports[sb->port - 1] = sb->bitrate;
+               if (sb->port <= sa->ports)
+                       ports[sb->port - 1] = sb->bitrate;
        }
        
        
@@ -136,11 +140,14 @@ int ngadmin_getBitrateLimits (struct ngadmin *nga, int *ports)
        struct attr *at;
        int ret = ERR_OK, port;
        struct attr_bitrate *pb;
+       struct swi_attr *sa;
        
        
        if (nga == NULL || ports == NULL)
                return ERR_INVARG;
-       else if (nga->current == NULL)
+       
+       sa = nga->current;
+       if (sa == NULL)
                return ERR_NOTLOG;
        
        
@@ -151,8 +158,9 @@ int ngadmin_getBitrateLimits (struct ngadmin *nga, int *ports)
        if (ret != ERR_OK)
                goto end;
        
+       filterAttributes(attr, ATTR_BITRATE_INPUT, ATTR_BITRATE_OUTPUT, ATTR_END);
        
-       for (port = 0; port < nga->current->ports; port++) {
+       for (port = 0; port < sa->ports; port++) {
                ports[2 * port + 0] = BITRATE_UNSPEC;
                ports[2 * port + 1] = BITRATE_UNSPEC;
        }
@@ -160,9 +168,11 @@ int ngadmin_getBitrateLimits (struct ngadmin *nga, int *ports)
        for (ln = attr->first; ln != NULL; ln = ln->next) {
                at = ln->data;
                pb = at->data;
-               if (at->attr == ATTR_BITRATE_INPUT)
+               if (pb->port > sa->ports)
+                       continue;
+               else if (at->attr == ATTR_BITRATE_INPUT)
                        ports[(pb->port - 1) * 2 + 0] = pb->bitrate;
-               else if (at->attr == ATTR_BITRATE_OUTPUT)
+               else
                        ports[(pb->port - 1) * 2 + 1] = pb->bitrate;
        }
        
index efe9ad855b2a6080f11fbb8f6bc85d8ade239676..03bb3ee05eb8c97586353b2185ace406c9ed847c 100644 (file)
@@ -15,12 +15,11 @@ int ngadmin_upgradeFirmware (struct ngadmin *nga, const char *filename)
        else if (nga->current == NULL)
                return ERR_NOTLOG;
        
-       /*
-       Firmware upgrade is not yet implemented. 
-       This would require much more work and the use of a TFTP client. 
-       Overall, it could be quite dangerous, as the switch may not check the binary 
-       content sent to it. 
-       */
+       /* firmware upgrade is not yet implemented
+        * this would require much more work and the use of a TFTP client
+        * overall, it could be quite dangerous, as the switch may not check
+        * the binary content sent to it
+        */
        
        return ERR_NOTIMPL;
 }
index daa7f471632733ced114065179b889374b609535..be4073847a7cc435e802cf080dc4b83bbd11d116 100644 (file)
@@ -13,11 +13,15 @@ int ngadmin_getMirror (struct ngadmin *nga, char *ports)
        List *attr;
        struct attr *at;
        int ret = ERR_OK;
+       struct swi_attr *sa;
+       struct attr_mirror *am;
        
        
        if (nga == NULL || ports == NULL)
                return ERR_INVARG;
-       else if (nga->current == NULL)
+       
+       sa = nga->current;
+       if (sa == NULL)
                return ERR_NOTLOG;
        
        
@@ -29,11 +33,22 @@ int ngadmin_getMirror (struct ngadmin *nga, char *ports)
        
        filterAttributes(attr, ATTR_MIRROR, ATTR_END);
        
-       memset(ports, 0, 1 + nga->current->ports);
+       memset(ports, 0, 1 + sa->ports);
        
        if (attr->first != NULL) {
                at = attr->first->data;
-               memcpy(ports, at->data, 1 + nga->current->ports);
+               am = at->data;
+               
+               if (am->outport == 0) {
+                       memset(ports, 0, 1 + sa->ports);
+               } else if (am->outport > 0 && at->size >= 1 + sa->ports) {
+                       if (at->size < sizeof(struct attr_mirror) + sa->ports) {
+                               ret = ERR_INVARG;
+                               goto end;
+                       }
+                       ports[0] = am->outport;
+                       memcpy(ports + 1, am->ports, sa->ports);
+               }
        }
        
        
@@ -48,8 +63,8 @@ end:
 int ngadmin_setMirror (struct ngadmin *nga, const char *ports)
 {
        List *attr;
-       char *p;
        struct swi_attr *sa;
+       struct attr_mirror *am;
        
        
        if (nga == NULL)
@@ -60,17 +75,19 @@ int ngadmin_setMirror (struct ngadmin *nga, const char *ports)
                return ERR_NOTLOG;
        
        
-       p = malloc(1 + sa->ports);
-       if (p == NULL)
+       am = malloc(sizeof(struct attr_mirror) + sa->ports);
+       if (am == NULL)
                return ERR_MEM;
        
-       if (ports == NULL)
-               memset(p, 0, 1 + sa->ports);
-       else
-               memcpy(p, ports, 1 + sa->ports);
+       if (ports == NULL) {
+               am->outport = 0;
+       } else {
+               am->outport = ports[0];
+               memcpy(am->ports, ports + 1, sa->ports);
+       }
        
        attr = createEmptyList();
-       pushBackList(attr, newAttr(ATTR_MIRROR, 1 + sa->ports, p));
+       pushBackList(attr, newAttr(ATTR_MIRROR, sizeof(struct attr_mirror) + sa->ports, am));
        
        
        return writeRequest(nga, attr);
index 93497726f8591e7fcb6c050100193f69b1e99566..15d0c908e77ab3c097b3c5db0b1458f5dbd39236 100644 (file)
@@ -21,15 +21,15 @@ int ngadmin_getIGMPConf (struct ngadmin *nga, struct igmp_conf *ic)
        else if (nga->current == NULL)
                return ERR_NOTLOG;
        
-       /*
-       ATTR_IGMP_ENABLE_VLAN
-       ATTR_IGMP_BLOCK_UNK
-       ATTR_IGMP_VALID_V3
-       
-       Apparently, read-querying these attributes at the same time causes the switch to reply garbage. 
-       Here we are forced to do like the official win app and send a separate request for each attribute. 
-       */
-       
+       /* ATTR_IGMP_ENABLE_VLAN
+        * ATTR_IGMP_BLOCK_UNK
+        * ATTR_IGMP_VALID_V3
+        *
+        * apparently, read-querying these attributes at the same time causes
+        * the switch to reply garbage
+        * here we are forced to do like the official win app and send a
+        * separate request for each attribute
+        */
        
        attr = createEmptyList();
        memset(ic, 0, sizeof(struct igmp_conf));
index 0ad90561c9eb70443ff5357cf928793d03b9e674..e10659620a2b765639c00aa3947b43af2cc7d0e1 100644 (file)
@@ -116,22 +116,20 @@ int forceInterface (struct ngadmin *nga)
        int ret;
        
        
-       /*
-       As described bellow, when you have multiple interfaces, this forces the packet 
-       to go to a particular interface. 
-       */
+       /* as described bellow, when you have multiple interfaces, this
+        * forces the packet to go to a particular interface
+        */
        ret = setsockopt(nga->sock, SOL_SOCKET, SO_BINDTODEVICE, nga->iface, strlen(nga->iface) + 1);
        if (ret < 0) {
                perror("setsockopt(SO_BINDTODEVICE)");
                return ret;
        }
        
-       /*
-       If the switch's IP is not in your network range, for instance because you do 
-       not have DHCP  enabled or you started the switch after it, this allows to 
-       bypass the routing tables and consider every address is directly reachable on 
-       the interface. 
-       */
+       /* if the switch's IP is not in your network range, for instance
+        * because you do not have DHCP  enabled or you started the switch
+        * after your DHCP server, this allows to bypass the routing tables
+        * and consider every address is directly reachable on the interface
+        */
        ret = 1;
        ret = setsockopt(nga->sock, SOL_SOCKET, SO_DONTROUTE, &ret, sizeof(ret));
        if (ret <0) {
@@ -169,10 +167,8 @@ void prepareSend (struct ngadmin *nga, struct nsdp_cmd *nc, unsigned char code)
        memcpy(&nc->client_mac, &nga->localmac, ETH_ALEN);
        nc->remote_addr.sin_family = AF_INET;
        nc->remote_addr.sin_port = htons(SWITCH_PORT);
-       if (sa != NULL) {
+       if (sa != NULL)
                memcpy(&nc->switch_mac, &sa->mac, ETH_ALEN);
-               nc->ports = sa->ports;
-       }
        
        /* destination address selection */
        if (sa != NULL && !nga->keepbroad)
@@ -196,10 +192,8 @@ void prepareRecv (struct ngadmin *nga, struct nsdp_cmd *nc, unsigned char code)
        memcpy(&nc->client_mac, &nga->localmac, ETH_ALEN);
        nc->remote_addr.sin_family = AF_INET;
        nc->remote_addr.sin_port = htons(SWITCH_PORT);
-       if (sa != NULL) {
+       if (sa != NULL)
                memcpy(&nc->switch_mac, &sa->mac, ETH_ALEN);
-               nc->ports = sa->ports;
-       }
        
        /* set filter on switch IP */
        if (sa == NULL)
@@ -287,7 +281,8 @@ int writeRequest (struct ngadmin *nga, List *attr)
        i = sendNsdpPacket(nga->sock, &nc, attr);
        
        /* the list will be filled again by recvNgPacket
-       but normally it will be still empty */
+        * but normally it will be still empty
+        */
        clearList(attr, (void(*)(void*))freeAttr);
        
        if (i >= 0) {
index 0b4afc2e20148fddcbcc8339b58055890aff90a8..0c7353362c720826e348135abc2a8677613c951e 100644 (file)
@@ -15,13 +15,15 @@ int ngadmin_getPortsStatus (struct ngadmin *nga, unsigned char *ports)
        struct attr *at;
        int ret = ERR_OK;
        struct attr_port_status *ps;
+       struct swi_attr *sa;
        
        
        if (nga == NULL || ports == NULL)
                return ERR_INVARG;
-       else if (nga->current == NULL)
-               return ERR_NOTLOG;
        
+       sa = nga->current;
+       if (sa == NULL)
+               return ERR_NOTLOG;
        
        attr = createEmptyList();
        pushBackList(attr, newEmptyAttr(ATTR_PORT_STATUS));
@@ -31,12 +33,13 @@ int ngadmin_getPortsStatus (struct ngadmin *nga, unsigned char *ports)
        
        filterAttributes(attr, ATTR_PORT_STATUS, ATTR_END);
        
-       memset(ports, SPEED_UNK, nga->current->ports);
+       memset(ports, SPEED_UNK, sa->ports);
        
        for (ln = attr->first; ln != NULL; ln = ln->next) {
                at = ln->data;
                ps = at->data;
-               ports[ps->port - 1] = ps->status;
+               if (ps->port <= sa->ports)
+                       ports[ps->port - 1] = ps->status;
        }
        
 end:
@@ -47,7 +50,6 @@ end:
 }
 
 
-
 int ngadmin_getPortsStatistics (struct ngadmin *nga, struct port_stats *ps)
 {
        List *attr;
@@ -55,11 +57,14 @@ int ngadmin_getPortsStatistics (struct ngadmin *nga, struct port_stats *ps)
        struct attr *at;
        int ret = ERR_OK;
        struct attr_port_stat *aps;
+       struct swi_attr *sa;
        
        
        if (nga == NULL || ps == NULL)
                return ERR_INVARG;
-       else if (nga->current == NULL)
+       
+       sa = nga->current;
+       if (sa == NULL)
                return ERR_NOTLOG;
        
        attr = createEmptyList();
@@ -70,14 +75,16 @@ int ngadmin_getPortsStatistics (struct ngadmin *nga, struct port_stats *ps)
        
        filterAttributes(attr, ATTR_PORT_STATISTICS, ATTR_END);
        
-       memset(ps, 0, nga->current->ports * sizeof(struct port_stats));
+       memset(ps, 0, sa->ports * sizeof(struct port_stats));
        
        for (ln = attr->first; ln != NULL; ln = ln->next) {
                at = ln->data;
                aps = at->data;
-               ps[aps->port -1].recv = aps->recv;
-               ps[aps->port -1].sent = aps->sent;
-               ps[aps->port -1].crc = aps->crc;
+               if (aps->port <= sa->ports) {
+                       ps[aps->port -1].recv = aps->recv;
+                       ps[aps->port -1].sent = aps->sent;
+                       ps[aps->port -1].crc = aps->crc;
+               }
        }
        
 end:
@@ -101,7 +108,6 @@ int ngadmin_resetPortsStatistics (struct ngadmin *nga)
 }
 
 
-
 int ngadmin_cabletest (struct ngadmin *nga, struct cabletest *ct, int nb)
 {
        List *attr;
index 553c87878503cfb12d5ca97df66f85f6e96d7b38..e31648afcdd9592b593b9a246fd5e9af7afe3c34 100644 (file)
@@ -65,13 +65,15 @@ int ngadmin_getQOSValues (struct ngadmin *nga, char *ports)
        struct attr *at;
        int ret = ERR_OK, port;
        struct attr_qos *aq;
+       struct swi_attr *sa;
        
        
        if (nga == NULL || ports == NULL)
                return ERR_INVARG;
-       else if (nga->current == NULL)
-               return ERR_NOTLOG;
        
+       sa = nga->current;
+       if (sa == NULL)
+               return ERR_NOTLOG;
        
        attr = createEmptyList();
        pushBackList(attr, newEmptyAttr(ATTR_QOS_CONFIG));
@@ -81,13 +83,14 @@ int ngadmin_getQOSValues (struct ngadmin *nga, char *ports)
        
        filterAttributes(attr, ATTR_QOS_CONFIG, ATTR_END);
        
-       for (port = 0; port < nga->current->ports; port++)
+       for (port = 0; port < sa->ports; port++)
                ports[port] = PRIO_UNSPEC;
        
        for (ln = attr->first; ln != NULL; ln = ln->next) {
                at = ln->data;
                aq = at->data;
-               ports[aq->port - 1] = aq->prio;
+               if (aq->port <= sa->ports)
+                       ports[aq->port - 1] = aq->prio;
        }
        
        
index 43da03079109458cab993ddd1472b16c6512be4c..667464c987c17f50dd81c67a1d1abfc170da0169 100644 (file)
@@ -16,23 +16,27 @@ int ngadmin_scan (struct ngadmin *nga)
        List *attr, *swiList;
        struct swi_attr *sa;
        struct nsdp_cmd nc;
-       /*
-       sent by official win client:
-       ATTR_PRODUCT,
-       ATTR_UNK2,
-       ATTR_NAME,
-       ATTR_MAC,
-       ATTR_UNK5,
-       ATTR_IP,
-       ATTR_NETMASK,
-       ATTR_GATEWAY,
-       ATTR_DHCP,
-       ATTR_UNK12,
-       ATTR_FIRM_VER,
-       ATTR_UNK14,
-       ATTR_UNK15,
-       ATTR_END
-       */
+       /* sent by official win client:
+        * ATTR_PRODUCT
+        * ATTR_UNK2
+        * ATTR_NAME
+        * ATTR_MAC
+        * ATTR_UNK5
+        * ATTR_IP
+        * ATTR_NETMASK
+        * ATTR_GATEWAY
+        * ATTR_DHCP
+        * ATTR_UNK12
+        * ATTR_FIRM_VER
+        * ATTR_UNK14
+        * ATTR_UNK15
+        * ATTR_END
+        *
+        * one may be tempted to add ATTR_ENCPASS so we can now early if the
+        * switch uses password encryption, but this would cause (at least)
+        * switches that do not support this feature not to reply to the
+        * discovery request at all
+        */
        static const unsigned short hello[] = {
                ATTR_PRODUCT,
                ATTR_NAME,
@@ -137,6 +141,10 @@ int ngadmin_login (struct ngadmin *nga, int id)
        nga->current = sa;
        nga->encrypt_pass = false;
        
+       /* determine if the switch uses password encryption
+        * as explained in ngadmin_scan, it cannot be done at discovery
+        * stage
+        */
        attr = createEmptyList();
        pushBackList(attr, newEmptyAttr(ATTR_ENCPASS));
        ret = readRequest(nga, attr);
@@ -146,19 +154,21 @@ int ngadmin_login (struct ngadmin *nga, int id)
        filterAttributes(attr, ATTR_ENCPASS, ATTR_END);
        if (attr->first != NULL) {
                at = attr->first->data;
-               nga->encrypt_pass = (at->size == 4 && ntohl(*(unsigned int*)at->data) == 1);
+               nga->encrypt_pass = (at->size == 4 && *(unsigned int*)at->data == 1);
        }
        clearList(attr, (void(*)(void*))freeAttr);
        
-       /* Strangely, passwords must never be encrypted inside a read request,
-        * or it will be rejected. Seems more to be a firmware bug. */
+       /* strangely, passwords must never be encrypted inside a read request,
+        * or it will be rejected. Seems more to be a firmware bug
+        */
        pushBackList(attr, newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password)));
        ret = readRequest(nga, attr);
        if (ret == ERR_OK ) {
                /* login succeeded */
-               /* TODO: if keep broadcasting is disabled, connect() the UDP 
-               socket so icmp errors messages (port unreachable, TTL exceeded 
-               in transit, ...) can be received */
+               /* TODO: if keep broadcasting is disabled, connect() the UDP
+                * socket so icmp errors messages (port unreachable, TTL exceeded
+                * in transit, ...) can be received
+                */
        } else {
                /* login failed */
                nga->current = NULL;
index 2d3d536dc2ced61fbf69dcfbe6cb95f304f69245..441e142a1e4a4bd2fad71ce948bf7d1097198d25 100644 (file)
@@ -103,7 +103,7 @@ int ngadmin_getVLANPortConf (struct ngadmin *nga, unsigned char *ports)
                at = ln->data;
                avc = at->data;
 
-               if (at->size != sizeof(struct attr_vlan_conf) + sa->ports) {
+               if (at->size < sizeof(struct attr_vlan_conf) + sa->ports) {
                        ret = ERR_INVARG;
                        goto end;
                }
@@ -167,7 +167,7 @@ int ngadmin_setVLANPortConf (struct ngadmin *nga, const unsigned char *ports)
                at = ln->data;
                avc_old = at->data;
                
-               if (at->size != sizeof(struct attr_vlan_conf) + sa->ports) {
+               if (at->size < sizeof(struct attr_vlan_conf) + sa->ports) {
                        ret = ERR_INVARG;
                        free(avc_new);
                        goto end;
@@ -252,7 +252,7 @@ int ngadmin_getVLANDotAllConf (struct ngadmin *nga, unsigned short *vlans, unsig
                at = ln->data;
                avc = at->data;
                
-               if (at->size != sizeof(struct attr_vlan_conf) + sa->ports) {
+               if (at->size < sizeof(struct attr_vlan_conf) + sa->ports) {
                        ret = ERR_INVARG;
                        goto end;
                }
@@ -313,7 +313,7 @@ int ngadmin_getVLANDotConf (struct ngadmin *nga, unsigned short vlan, unsigned c
                at = ln->data;
                avc = at->data;
                
-               if (at->size != sizeof(struct attr_vlan_conf) + sa->ports) {
+               if (at->size < sizeof(struct attr_vlan_conf) + sa->ports) {
                        ret = ERR_INVARG;
                        goto end;
                }
@@ -379,7 +379,7 @@ int ngadmin_setVLANDotConf (struct ngadmin *nga, unsigned short vlan, const unsi
                        goto end;
                } else {
                        at = attr->first->data;
-                       if (at->size != sizeof(struct attr_vlan_conf) + sa->ports) {
+                       if (at->size < sizeof(struct attr_vlan_conf) + sa->ports) {
                                ret = ERR_INVARG;
                                goto end;
                        }
@@ -436,11 +436,14 @@ int ngadmin_getAllPVID (struct ngadmin *nga, unsigned short *ports)
        struct attr *at;
        int ret = ERR_OK;
        struct attr_pvid *ap;
+       struct swi_attr *sa;
        
        
        if (nga == NULL || ports == NULL)
                return ERR_INVARG;
-       else if (nga->current == NULL)
+       
+       sa = nga->current;
+       if (sa == NULL)
                return ERR_NOTLOG;
        
        
@@ -452,12 +455,13 @@ int ngadmin_getAllPVID (struct ngadmin *nga, unsigned short *ports)
        
        filterAttributes(attr, ATTR_VLAN_PVID, ATTR_END);
        
-       memset(ports, 0, nga->current->ports * sizeof(unsigned short));
+       memset(ports, 0, sa->ports * sizeof(unsigned short));
        
        for (ln = attr->first; ln != NULL; ln = ln->next) {
                at = ln->data;
                ap = at->data;
-               ports[ap->port - 1] = ap->vlan;
+               if (ap->port <= sa->ports)
+                       ports[ap->port - 1] = ap->vlan;
        }
        
        
index ccce647fefac17aca8f89c8647c3d3d54a5f3217..5a903a891d6372b07b8358c39c550e60bbc43c04 100644 (file)
@@ -1,3 +1,3 @@
 
-noinst_HEADERS = attr.h encoding.h list.h misc.h net.h protocol.h
+noinst_HEADERS = attr.h list.h misc.h net.h packet.h protocol.h
 
index 75ce384fcf100cdf8b6c38c097fff48ef65b615d..e85a00221b3b2002344817efd2b042ad932cf826 100644 (file)
@@ -73,5 +73,11 @@ void freeAttr (struct attr *at);
 void filterAttributes (List *attr, ...);
 
 
+int encodeAttr (struct attr *at);
+
+
+int decodeAttr (struct attr *at);
+
+
 #endif
 
diff --git a/raw/include/nsdp/encoding.h b/raw/include/nsdp/encoding.h
deleted file mode 100644 (file)
index 27ec812..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-
-#ifndef DEF_ENCODING
-#define DEF_ENCODING
-
-
-#include <stdbool.h>
-
-#include <netinet/ether.h>
-
-#include <nsdp/protocol.h>
-#include <nsdp/net.h>
-#include <nsdp/list.h>
-
-
-struct nsdp_packet {
-       union {
-               unsigned char *buffer;
-               struct nsdp_header *nh;
-       };
-       int maxlen;
-       struct attr_header *ah;
-};
-
-
-
-void initNsdpHeader (struct nsdp_header *nh, const struct nsdp_cmd *nc);
-
-
-bool extractNsdpHeader (const struct nsdp_header *nh, struct nsdp_cmd *nc);
-
-
-static inline void initNsdpPacket (struct nsdp_packet *np)
-{
-       np->ah = (struct attr_header*)np->nh->data;
-}
-
-
-static inline int getPacketTotalSize (const struct nsdp_packet *np)
-{
-       return ((unsigned char*)np->ah) - np->buffer;
-}
-
-
-int addPacketAttributes (struct nsdp_packet *np, const List* attr, unsigned char ports);
-
-
-int extractPacketAttributes (struct nsdp_packet *np, List *attr, unsigned char ports);
-
-
-#endif
-
index 401a1fbb886a0501a48688530e244b8c04192900..8620dd39bb4bdb26081c920337c291eaff78299e 100644 (file)
@@ -15,7 +15,6 @@ struct nsdp_cmd {
        struct ether_addr switch_mac;
        struct sockaddr_in remote_addr;
        unsigned int seqnum;
-       unsigned int ports;
        unsigned char code;
        unsigned char error;
        unsigned short attr_error;
diff --git a/raw/include/nsdp/packet.h b/raw/include/nsdp/packet.h
new file mode 100644 (file)
index 0000000..21c1569
--- /dev/null
@@ -0,0 +1,51 @@
+
+#ifndef DEF_ENCODING
+#define DEF_ENCODING
+
+
+#include <stdbool.h>
+
+#include <netinet/ether.h>
+
+#include <nsdp/protocol.h>
+#include <nsdp/net.h>
+#include <nsdp/list.h>
+
+
+struct nsdp_packet {
+       union {
+               unsigned char *buffer;
+               struct nsdp_header *nh;
+       };
+       int maxlen;
+       struct attr_header *ah;
+};
+
+
+
+void initNsdpHeader (struct nsdp_header *nh, const struct nsdp_cmd *nc);
+
+
+bool extractNsdpHeader (const struct nsdp_header *nh, struct nsdp_cmd *nc);
+
+
+static inline void initNsdpPacket (struct nsdp_packet *np)
+{
+       np->ah = (struct attr_header*)np->nh->data;
+}
+
+
+static inline int getPacketTotalSize (const struct nsdp_packet *np)
+{
+       return ((unsigned char*)np->ah) - np->buffer;
+}
+
+
+int addPacketAttributes (struct nsdp_packet *np, const List* attr);
+
+
+int extractPacketAttributes (struct nsdp_packet *np, List *attr);
+
+
+#endif
+
index a785e2c1b4ee1318091f5dcfcb49b15f22282381..e346de5a3355b530df712d5fd3dcd713d79ae29e 100644 (file)
@@ -147,14 +147,23 @@ struct attr_cabletest_result {
 } __attribute__((packed));
 
 
-/**
- * Note: this structure is not sent "as-is" on the wire.
+/* Note: this structure is not sent "as-is" on the wire.
  * A translation is done between the wire format (which uses somewhat not
- * trivial bitmap) and this simpler format. See encoding_attr.c for more details.
+ * trivial bitmap) and this simpler format. See attr.c for more details.
  */
 struct attr_vlan_conf {
-       unsigned short vlan;            /* port number */
-       unsigned char ports[0];         /* array, maps each port to a VLAN */
+       unsigned short vlan;            /* VLAN number */
+       unsigned char ports[0];         /* array, maps each port association with the VLAN */
+};
+
+
+/* Note: this structure is not sent "as-is" on the wire.
+ * A translation is done between the wire format (which uses somewhat not
+ * trivial bitmap) and this simpler format. See attr.c for more details.
+ */
+struct attr_mirror {
+       unsigned char outport;          /* port number on which traffic is sent */
+       unsigned char ports[0];         /* array, maps each port source mirror traffic */
 };
 
 
index cc047c9a7c7ae67875c2390c7a0a8281cef48ed4..f0c2a917e76a6e1a5fcbe034332c8bada86e4b9b 100644 (file)
@@ -1,8 +1,7 @@
 
 noinst_LTLIBRARIES = librawnsdp.la
-noinst_HEADERS = encoding_attr.h
 
-librawnsdp_la_SOURCES = attr.c encoding.c encoding_attr.c list.c misc.c net.c
+librawnsdp_la_SOURCES = attr.c list.c misc.c net.c packet.c
 librawnsdp_la_CPPFLAGS = -I$(top_srcdir)/raw/include/ -I$(top_srcdir)/lib/include/
 librawnsdp_la_CFLAGS = -fno-strict-aliasing
 librawnsdp_la_LIBADD = $(RT_LIBS)
index c8f2fcc49848409fae3f1eb1a80c6d1c99b1ba69..70f3a18760d21cd434dd5f27da82cb59daa10926 100644 (file)
@@ -1,16 +1,16 @@
 
 #include <stdarg.h>
+#include <errno.h>
 
+#include <ngadmin.h> /* FIXME */
 #include <nsdp/attr.h>
 #include <nsdp/protocol.h>
 
 
-
 struct attr* newAttr (unsigned short attr, unsigned short size, void *data)
 {
        struct attr *at;
        
-       
        at = malloc(sizeof(struct attr));
        if (at == NULL)
                return NULL;
@@ -19,7 +19,6 @@ struct attr* newAttr (unsigned short attr, unsigned short size, void *data)
        at->size = size;
        at->data = data;
        
-       
        return at;
 }
 
@@ -42,8 +41,7 @@ void filterAttributes (List *attr, ...)
        bool keep;
        
        
-       ln = attr->first;
-       while (ln != NULL) {
+       for (ln = attr->first; ln != NULL; ) {
                at = ln->data;
                
                va_start(ap, attr);
@@ -63,7 +61,623 @@ void filterAttributes (List *attr, ...)
                        destroyElement(attr, pr, (void(*)(void*))freeAttr);
                }
        }
+}
+
+
+static int ports_status_endecode (struct attr *at)
+{
+       struct attr_port_status *ps = at->data;
+       
+       if (at->size != sizeof(struct attr_port_status))
+               return -EMSGSIZE;
+       
+       if (ps->port < 1)
+               return -EINVAL;
+       
+       switch (ps->status) {
+       
+       case SPEED_DOWN:
+       case SPEED_10:
+       case SPEED_100:
+       case SPEED_1000:
+               return 0;
+       
+       default:
+               return -EINVAL;
+       }
+}
+
+
+static int port_stat_endecode (struct attr *at, bool encode)
+{
+       struct attr_port_stat *ps = at->data;
+       unsigned long long *v;
+       
+       if (at->size != sizeof(struct attr_port_stat))
+               return -EMSGSIZE;
+       
+       if (ps->port < 1)
+               return -EINVAL;
+       
+       for (v = &ps->recv; ((void*)v) - ((void*)ps) < (int)sizeof(struct attr_port_stat); v++)
+               *v = encode ? htobe64(*v) : be64toh(*v);
+       
+       return 0;
+}
+
+
+static int qos_endecode (struct attr *at)
+{
+       struct attr_qos *aq = at->data;
+       
+       if (at->size != sizeof(struct attr_qos))
+               return -EMSGSIZE;
+       
+       if (aq->port < 1)
+               return -EINVAL;
+       
+       if (aq->prio < PRIO_HIGH || aq->prio > PRIO_LOW)
+               return -EINVAL;
+       
+       return 0;
+}
+
+
+static int bitrate_endecode (struct attr *at, bool encode)
+{
+       struct attr_bitrate *sb = at->data;
+       
+       if (at->size != sizeof(struct attr_bitrate))
+               return -EMSGSIZE;
+       
+       if (sb->port < 1)
+               return -EINVAL;
+       
+       if (!encode)
+               sb->bitrate = ntohl(sb->bitrate);
+       
+       if (sb->bitrate < BITRATE_UNSPEC || sb->bitrate > BITRATE_512M)
+               return -EINVAL;
+       
+       if (encode)
+               sb->bitrate = htonl(sb->bitrate);
+       
+       return 0;
+}
+
+
+static int pvid_endecode (struct attr *at, bool encode)
+{
+       struct attr_pvid *ap = at->data;
+       
+       if (at->size != sizeof(struct attr_pvid))
+               return -EMSGSIZE;
+       
+       if (ap->port < 1)
+               return -EINVAL;
+       
+       if (!encode)
+               ap->vlan = ntohs(ap->vlan);
+       
+       if (ap->vlan < VLAN_MIN || ap->vlan > VLAN_DOT_MAX)
+               return -EINVAL;
+       
+       if (encode)
+               ap->vlan = htons(ap->vlan);
+       
+       return 0;
+}
+
+
+static int cabletest_do_endecode (struct attr *at)
+{
+       struct attr_cabletest_do *acd = at->data;
+       
+       if (at->size != sizeof(struct attr_cabletest_do))
+               return -EMSGSIZE;
+       
+       if (acd->port < 1 || acd->action != 1)
+               return -EINVAL;
+       
+       return 0;
+}
+
+
+static int cabletest_result_endecode (struct attr *at, bool encode)
+{
+       struct attr_cabletest_result *acr = at->data;
+       
+       /* Note: this attribute is special
+        * - when sent by the client, it contains the port number whe want to
+        *   get cabletest results from
+        * - when the switch replies, it contains the actual test results data
+        */
+       
+       /* no need to check the size, the only possible value under 1
+        * is 0 and in that case the decoder is not called
+        */
+       if (acr->port < 1)
+               return -EINVAL;
+       
+       if (at->size == 1)
+               return 0;
+       
+       if (at->size != sizeof(struct attr_cabletest_result))
+               return -EMSGSIZE;
+       
+       if (encode) {
+               acr->v1 = htonl(acr->v1);
+               acr->v2 = htonl(acr->v2);
+       } else {
+               acr->v1 = ntohl(acr->v1);
+               acr->v2 = ntohl(acr->v2);
+       }
+       
+       return 0;
+}
+
+
+static int igmp_vlan_endecode (struct attr *at, bool encode)
+{
+       struct attr_igmp_vlan *aiv = at->data;
+       
+       if (at->size != sizeof(struct attr_igmp_vlan))
+               return -EMSGSIZE;
+       
+       if (!encode) {
+               aiv->enable = ntohs(aiv->enable);
+               aiv->vlan = ntohs(aiv->vlan);
+       }
+       
+       aiv->enable = (aiv->enable != 0);
+       if (aiv->vlan < VLAN_MIN || aiv->vlan > VLAN_DOT_MAX)
+               return -EINVAL;
+       
+       if (encode) {
+               aiv->enable = htons(aiv->enable);
+               aiv->vlan = htons(aiv->vlan);
+       }
+       
+       return 0;
+}
+
+
+static int mirror_encode (struct attr *at)
+{
+       struct attr_mirror *am = at->data;
+       unsigned char p, ports, *r;
+       unsigned int sz;
+       
+       
+       /* no need to check attribute size, since
+        * sizeof(struct attr_mirror) == 1 and encoder is not
+        * called when attribute size is zero (ie empty attribute)
+        *
+        * am->outport encodes the outgoing mirror port and the array
+        * the ports from which the data is copied, it must not be empty
+        *
+        * am->outport == 0 is allowed and means mirroring is disabled
+        * but in that case the ports array must be empty
+        */
+       ports = at->size - sizeof(struct attr_mirror);
+       if ((am->outport == 0) ^ (ports == 0))
+               return -EINVAL;
+       
+       sz = 3 + ((ports - 1) >> 3);
+       r = malloc(sz);
+       if (r == NULL)
+               return -ENOMEM;
+       memset(r, 0, sz);
+       
+       r[0] = am->outport;
+       
+       /* FIXME: if ports > 8 */
+       for (p = 1; p <= ports; p++) {
+               if (am->outport != p)
+                       r[2] |= (am->ports[p] & 1) << (8 - p);
+       }
+       
+       free(at->data);
+       at->data = r;
+       at->size = sz;
+       
+       
+       return 0;
+}
+
+
+static int mirror_decode (struct attr *at)
+{
+       struct attr_mirror *am;
+       unsigned char p, ports, *r = at->data;
+       unsigned int sz;
+       
+       
+       if (at->size < 3)
+               return -EMSGSIZE;
+       
+       /* note: we cannot compute the exact amount of ports from here,
+        * instead we have the immediate superior multiple of 8
+        * it will be the user's job to ignore extra entries
+        */
+       ports = ((at->size - 2) << 3);
+       
+       /* r[0] == 0 is allowed and means mirroring is disabled */
+       if (r[0] == 0)
+               ports = 0;
+       sz = sizeof(struct attr_mirror) + ports;
+       
+       am = malloc(sz);
+       if (am == NULL)
+               return -ENOMEM;
+       memset(am, 0, sz);
+       
+       am->outport = r[0];
+       
+       /* FIXME: if ports > 8 */
+       for (p = 1; p <= ports; p++)
+               am->ports[p] = (r[2] >> (8 - p)) & 1;
+       
+       free(at->data);
+       at->data = am;
+       at->size = sz;
+       
+       
+       return 0;
+}
+
+
+static int vlan_port_encode (struct attr *at)
+{
+       struct attr_vlan_conf *avc = at->data;
+       unsigned char p, ports, *r;
+       unsigned int sz;
+       
+       
+       /* just a header is valid */
+       if (at->size < sizeof(struct attr_vlan_conf))
+               return -EMSGSIZE;
+       ports = at->size - sizeof(struct attr_vlan_conf);
+       
+       if (avc->vlan < VLAN_MIN || avc->vlan > VLAN_PORT_MAX)
+               return -EINVAL;
+       
+       if (ports == 0)
+               sz = 2;
+       else
+               sz = (2 + 1 + ((ports - 1) >> 3));
+       
+       r = malloc(sz);
+       if (r == NULL)
+               return -ENOMEM;
+       
+       memset(r, 0, sz);
+       *(unsigned short*)r = htons(avc->vlan);
+       
+       /* FIXME: if ports > 8 */
+       for (p = 0; p < ports; p++) {
+               if (avc->ports[p] == VLAN_UNTAGGED)
+                       r[2] |= (1 << (7 - p));
+       }
+       
+       free(at->data);
+       at->data = r;
+       at->size = sz;
+       
+       
+       return 0;
+}
+
+
+static int vlan_port_decode (struct attr *at)
+{
+       unsigned char p, ports, *r = at->data;
+       struct attr_vlan_conf *avc;
+       unsigned int sz;
+       
+       
+       if (at->size < 2)
+               return -EMSGSIZE;
+       
+       /* note: we cannot compute the exact amount of ports from here,
+        * instead we have the immediate superior multiple of 8
+        * it will be the user's job to ignore extra entries
+        */
+       ports = ((at->size - 2) << 3);
+       
+       sz = sizeof(struct attr_vlan_conf) + ports;
+       avc = malloc(sz);
+       if (avc == NULL)
+               return -ENOMEM;
+       
+       avc->vlan = ntohs(*(unsigned short*)r);
+       
+       /* FIXME: if ports > 8 */
+       for (p = 0; p < ports; p++) {
+               if ((r[2] >> (7 - p)) & 1)
+                       avc->ports[p] = VLAN_UNTAGGED;
+               else
+                       avc->ports[p] = VLAN_NO;
+       }
+       
+       free(at->data);
+       at->data = avc;
+       at->size = sz;
+       
+       
+       return 0;
+}
+
+
+static int vlan_dot_encode (struct attr *at)
+{
+       struct attr_vlan_conf *avc = at->data;
+       unsigned char p, ports, *r, fl;
+       unsigned int sz;
+       
+       
+       /* just a header is valid */
+       if (at->size < sizeof(struct attr_vlan_conf))
+               return -EMSGSIZE;
+       ports = at->size - sizeof(struct attr_vlan_conf);
+       
+       if (avc->vlan < VLAN_MIN || avc->vlan > VLAN_DOT_MAX)
+               return -EINVAL;
+       
+       if (ports == 0)
+               sz = 2;
+       else
+               sz = 2 + 2 * (1 + ((ports - 1) >> 3));
+       
+       r = malloc(sz);
+       if (r == NULL)
+               return -EMSGSIZE;
+       
+       memset(r, 0, sz);
+       *(unsigned short*)r = htons(avc->vlan);
+       
+       /* FIXME: if ports > 8 */
+       for (p = 0; p < ports; p++) {
+               fl = (1 << (7 - p));
+               switch (avc->ports[p]) {
+               case VLAN_TAGGED:
+                       r[3] |= fl;
+                       /* a tagged VLAN is also marked as untagged
+                        * so do not put a "break" here
+                        */
+               case VLAN_UNTAGGED:
+                       r[2] |= fl;
+               }
+       }
+       
+       
+       free(at->data);
+       at->data = r;
+       at->size = sz;
+       
+       
+       return 0;
+}
+
+
+static int vlan_dot_decode (struct attr *at)
+{
+       unsigned char p, ports, *r = at->data;
+       struct attr_vlan_conf *avc;
+       unsigned int sz;
+       
+       
+       /* attribute size must be a multiple of 2 because there are
+        * 2 bytes (1 for tagged and 1 for untagged) per block of
+        * 8 ports, plus the 2 first bytes for the VLAN id
+        */
+       if (at->size < 2 || (at->size & 1) != 0)
+               return -EMSGSIZE;
+       
+       /* note: we cannot compute the exact amount of ports from here,
+        * instead we have the immediate superior multiple of 8
+        * it will be the user's job to ignore extra entries
+        */
+       ports = ((at->size - 2) / 2) << 3;
+       
+       sz = sizeof(struct attr_vlan_conf) + ports;
+       avc = malloc(sz);
+       if (avc == NULL)
+               return -ENOMEM;
+       
+       avc->vlan = ntohs(*(unsigned short*)r);
+       
+       /* FIXME: if ports > 8 */
+       for (p = 0; p < ports; p++) {
+               if ((r[3] >> (7 - p)) & 1)
+                       avc->ports[p] = VLAN_TAGGED;
+               else if ((r[2] >> (7 - p)) & 1)
+                       avc->ports[p] = VLAN_UNTAGGED;
+               else
+                       avc->ports[p] = VLAN_NO;
+       }
+       
+       free(at->data);
+       at->data = avc;
+       at->size = sz;
+       
        
+       return 0;
+}
+
+
+static int processAttr (struct attr *at, bool encode)
+{
+       unsigned char *byte = at->data;
+       unsigned short *word = at->data;
+       unsigned int *dword = at->data;
+       
+       
+       /* empty attributes are not processed */
+       if (at->size == 0)
+               return 0;
+       
+       if (at->data == NULL)
+               return -EFAULT;
+       
+       switch (at->attr) {
+       
+       case ATTR_MAC:
+               if (at->size != ETH_ALEN)
+                       return -EMSGSIZE;
+               return 0;
+       
+       case ATTR_IP:
+       case ATTR_NETMASK:
+       case ATTR_GATEWAY:
+               /* IP addresses are kept in network byte order even on the host */
+               if (at->size != sizeof(struct in_addr))
+                       return -EMSGSIZE;
+               
+               return 0;
+       
+       case ATTR_PORTS_COUNT:
+               if (at->size != 1)
+                       return -EMSGSIZE;
+               
+               return 0;
+       
+       case ATTR_RESTART:
+       case ATTR_DEFAULTS:
+       case ATTR_STATS_RESET:
+       case ATTR_STORM_ENABLE:
+       case ATTR_IGMP_BLOCK_UNK:
+       case ATTR_IGMP_VALID_V3:
+               if (at->size != 1)
+                       return -EMSGSIZE;
+               
+               *byte = (*byte != 0);
+               
+               return 0;
+       
+       case ATTR_DHCP:
+               if (at->size != 2)
+                       return -EMSGSIZE;
+               
+               if (!encode)
+                       *word = ntohs(*word);
+               
+               *word = (*word != 0);
+               
+               if (encode)
+                       *word = htons(*word);
+               
+               return 0;
+       
+       case ATTR_ENCPASS:
+               if (at->size != 4)
+                       return -EMSGSIZE;
+               
+               if (!encode)
+                       *dword = ntohl(*dword);
+               
+               *dword = (*dword != 0);
+               
+               if (encode)
+                       *dword = htonl(*dword);
+               
+               return 0;
+       
+       case ATTR_VLAN_TYPE:
+               if (at->size != 1)
+                       return -EMSGSIZE;
+               
+               /* no need to check if *byte < VLAN_DISABLED because
+                * byte is unsigned and VLAN_DISABLED is 0 */
+               if (*byte > VLAN_DOT_ADV)
+                       return -EINVAL;
+               
+               return 0;
+       
+       case ATTR_QOS_TYPE:
+               if (at->size != 1)
+                       return -EMSGSIZE;
+               
+               if (*byte < QOS_PORT || *byte > QOS_DOT)
+                       return -EINVAL;
+               
+               return 0;
+       
+       case ATTR_QOS_CONFIG:
+               return qos_endecode(at);
+       
+       case ATTR_VLAN_DESTROY:
+               if (at->size != 2)
+                       return -EMSGSIZE;
+               
+               if (!encode)
+                       *word = ntohs(*word);
+               
+               if (*word < VLAN_MIN || *word > VLAN_DOT_MAX)
+                       return -EINVAL;
+               
+               if (encode)
+                       *word = htons(*word);
+               
+               return 0;
+       
+       case ATTR_PORT_STATUS:
+               return ports_status_endecode(at);
+       
+       case ATTR_PORT_STATISTICS:
+               return port_stat_endecode(at, encode);
+       
+       case ATTR_BITRATE_INPUT:
+       case ATTR_BITRATE_OUTPUT:
+       case ATTR_STORM_BITRATE:
+               return bitrate_endecode(at, encode);
+       
+       case ATTR_VLAN_PVID:
+               return pvid_endecode(at, encode);
+       
+       case ATTR_CABLETEST_DO:
+               return cabletest_do_endecode(at);
+       
+       case ATTR_CABLETEST_RESULT:
+               return cabletest_result_endecode(at, encode);
+       
+       case ATTR_IGMP_ENABLE_VLAN:
+               return igmp_vlan_endecode(at, encode);
+       
+       case ATTR_MIRROR:
+               if (encode)
+                       return mirror_encode(at);
+               else
+                       return mirror_decode(at);
+       
+       case ATTR_VLAN_PORT_CONF:
+               if (encode)
+                       return vlan_port_encode(at);
+               else
+                       return vlan_port_decode(at);
+       
+       case ATTR_VLAN_DOT_CONF:
+               if (encode)
+                       return vlan_dot_encode(at);
+               else
+                       return vlan_dot_decode(at);
+       
+       /* undefined attributes are not modified */
+       default:
+               return 0;
+       }
+}
+
+
+int encodeAttr (struct attr *at)
+{
+       return processAttr(at, true);
+}
+
+
+int decodeAttr (struct attr *at)
+{
+       return processAttr(at, false);
 }
 
 
diff --git a/raw/src/encoding.c b/raw/src/encoding.c
deleted file mode 100644 (file)
index 0d8e889..0000000
+++ /dev/null
@@ -1,192 +0,0 @@
-
-#include <string.h>
-#include <errno.h>
-
-#include <nsdp/attr.h>
-#include <nsdp/encoding.h>
-#include "encoding_attr.h"
-
-
-
-void initNsdpHeader (struct nsdp_header *nh, const struct nsdp_cmd *nc)
-{
-       memset(nh, 0, sizeof(struct nsdp_header));
-       nh->version = NSDP_VERSION;
-       nh->code = nc->code;
-       nh->error = nc->error;
-       nh->attr = htons(nc->attr_error);
-       
-       memcpy(nh->client_mac, &nc->client_mac, ETH_ALEN);
-       memcpy(nh->switch_mac, &nc->switch_mac, ETH_ALEN);
-       
-       nh->seqnum = htonl(nc->seqnum);
-       memcpy(nh->proto_id, NSDP_PROTOID, 4);
-}
-
-
-bool extractNsdpHeader (const struct nsdp_header *nh, struct nsdp_cmd *nc)
-{
-       unsigned int i;
-       
-       
-       if (nh->version != NSDP_VERSION)
-               return false;
-       
-       if (nc->code > 0 && nh->code != nc->code)
-               return false;
-       nc->code = nh->code;
-       
-       nc->error = nh->error;
-       nc->attr_error = ntohs(nh->attr);
-       
-       if (nh->unk1 != 0)
-               return false;
-       
-       if (*(unsigned short*)nh->unk2 != 0)
-               return false;
-       
-       for (i = 0; i < ETH_ALEN && nc->client_mac.ether_addr_octet[i] == 0; i++);
-       if (i < ETH_ALEN && memcmp(nh->client_mac, &nc->client_mac, ETH_ALEN) != 0)
-               return false;
-       memcpy(&nc->client_mac, nh->client_mac, ETH_ALEN);
-       
-       for (i = 0; i < ETH_ALEN && nc->switch_mac.ether_addr_octet[i] == 0; i++);
-       if (i < ETH_ALEN && memcmp(nh->switch_mac, &nc->switch_mac, ETH_ALEN) != 0)
-               return false;
-       memcpy(&nc->switch_mac, nh->switch_mac, ETH_ALEN);
-       
-       if (nc->seqnum > 0 && ntohl(nh->seqnum) != nc->seqnum)
-               return false;
-       nc->seqnum = ntohl(nh->seqnum);
-       
-       if (memcmp(nh->proto_id, NSDP_PROTOID, 4) != 0)
-               return false;
-       
-       if (*(unsigned int*)nh->unk3 != 0)
-               return false;
-       
-       return true;
-}
-
-
-static void addPacketAttr (struct nsdp_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);
-}
-
-
-int addPacketAttributes (struct nsdp_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 nsdp_packet *np, List *attr, unsigned char ports)
-{
-       struct attr *at;
-       const struct attr_handler *ah;
-       int ret = 0;
-       unsigned short size;
-       bool valid;
-       
-       
-       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(unsigned char));
-                       memcpy(at->data, np->ah->data, size);
-               }
-               
-               /* decode attribute data */
-               valid = true;
-               
-               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/raw/src/encoding_attr.c b/raw/src/encoding_attr.c
deleted file mode 100644 (file)
index acb706f..0000000
+++ /dev/null
@@ -1,548 +0,0 @@
-
-#include <ngadmin.h> /* FIXME */
-#include <nsdp/protocol.h>
-#include "encoding_attr.h"
-
-
-#define UNUSED                 __attribute__((unused))
-#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_DOT_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_DOT_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_DOT_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_DOT_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_DOT_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_port_decode (struct attr *at, unsigned char ports)
-{
-       char *r = at->data;
-       struct attr_vlan_conf *avc;
-       int port;
-       
-       
-       if (at->size != (2 + 1 + ((ports - 1) >> 3)))
-               return false;
-       
-       avc = malloc(sizeof(struct attr_vlan_conf) + ports);
-       if (avc == NULL)
-               return false;
-       
-       avc->vlan = ntohs(*(unsigned short*)r);
-       r += 2;
-       
-       for (port = 0; port < ports; port++) {
-               /* FIXME: if ports > 8 */
-               if ((r[0] >> (7 - port)) & 1)
-                       avc->ports[port] = VLAN_UNTAGGED;
-               else
-                       avc->ports[port] = VLAN_NO;
-       }
-       
-       free(at->data);
-       at->data = avc;
-       at->size = sizeof(struct attr_vlan_conf) + ports;
-       
-       
-       return true;
-}
-
-
-static bool vlan_port_encode (struct attr *at, unsigned char ports)
-{
-       struct attr_vlan_conf *avc = at->data;
-       char *r;
-       unsigned int size, port;
-       
-       
-       if (avc->vlan < VLAN_MIN || avc->vlan > VLAN_PORT_MAX)
-               return false;
-       
-       /* just a header is valid */
-       if (at->size == sizeof(struct attr_vlan_conf))
-               size = 2;
-       else if (at->size == sizeof(struct attr_vlan_conf) + ports)
-               size = (2 + 1 + ((ports - 1) >> 3));
-       else
-               return false;
-       
-       r = malloc(size);
-       if (r == NULL)
-               return false;
-       
-       memset(r, 0, size);
-       *(unsigned short*)r = htons(avc->vlan);
-       
-       if (size == 2)
-               goto end;
-       
-       r += 2;
-
-       for (port = 0; port < ports; port++) {
-               /* FIXME: if ports > 8 */
-               if (avc->ports[port] == VLAN_UNTAGGED)
-                       r[0] |= (1 << (7 - port));
-       }
-
-       r -= 2;
-       
-end:
-       free(at->data);
-       at->data = r;
-       at->size = size;
-       
-       
-       return true;
-}
-
-
-static bool vlan_dot_decode (struct attr *at, unsigned char ports)
-{
-       char *r = at->data;
-       struct attr_vlan_conf *avc;
-       int port;
-       
-       
-       if (at->size != (2 + 2 * (1 + ((ports - 1) >> 3))))
-               return false;
-       
-       avc = malloc(sizeof(struct attr_vlan_conf) + ports);
-       if (avc == NULL)
-               return false;
-       
-       avc->vlan = ntohs(*(unsigned short*)r);
-       r += 2;
-       
-       for (port = 0; port < ports; port++) {
-               /* FIXME: if ports > 8 */
-               if ((r[1] >> (7 - port)) & 1)
-                       avc->ports[port] = VLAN_TAGGED;
-               else if ((r[0] >> (7 - port)) & 1)
-                       avc->ports[port] = VLAN_UNTAGGED;
-               else
-                       avc->ports[port] = VLAN_NO;
-       }
-       
-       free(at->data);
-       at->data = avc;
-       at->size = sizeof(struct attr_vlan_conf) + ports;
-       
-       
-       return true;
-}
-
-
-static bool vlan_dot_encode (struct attr *at, unsigned char ports)
-{
-       struct attr_vlan_conf *avc = at->data;
-       char *r, fl;
-       unsigned int size, port;
-       
-       
-       if (avc->vlan < VLAN_MIN || avc->vlan > VLAN_DOT_MAX)
-               return false;
-       
-       /* just a header is valid */
-       if (at->size == sizeof(struct attr_vlan_conf))
-               size = 2;
-       else if (at->size == sizeof(struct attr_vlan_conf) + 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(avc->vlan);
-       
-       if (size == 2)
-               goto end;
-       
-       r += 2;
-       
-       for (port = 0; port < ports; port++) {
-               /* FIXME: if ports > 8 */
-               fl = (1 << (7 - port));
-               switch (avc->ports[port]) {
-               case VLAN_TAGGED:
-                       r[1] |= fl;
-                       /* a tagged VLAN is also marked as untagged
-                        * so do not put a "break" here */
-               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_ENCPASS, 4, 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_PORT_CONF, 0, vlan_port_encode, vlan_port_decode),
-       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/encoding_attr.h b/raw/src/encoding_attr.h
deleted file mode 100644 (file)
index ba6146c..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-
-#ifndef DEF_ENCODING_ATTR
-#define DEF_ENCODING_ATTR
-
-
-#include <stdbool.h>
-
-#include <nsdp/attr.h>
-
-
-
-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);
-
-
-#endif
-
index e5af939c39d72f89bd4aa91b2a7201f825dac7c7..83a69f3c9ad68a4f9405676e7798354a6de4b20e 100644 (file)
@@ -8,7 +8,7 @@
 #include <poll.h>
 
 #include <nsdp/net.h>
-#include <nsdp/encoding.h>
+#include <nsdp/packet.h>
 
 
 static inline void timespec_add (struct timespec *tsa, const struct timespec *tsb)
@@ -57,7 +57,7 @@ int sendNsdpPacket (int sock, const struct nsdp_cmd *nc, const List *attr)
        initNsdpPacket(&np);
        initNsdpHeader(np.nh, nc);
        
-       ret = addPacketAttributes(&np, attr, nc->ports);
+       ret = addPacketAttributes(&np, attr);
        if (ret < 0)
                return ret;
        
@@ -139,7 +139,7 @@ int recvNsdpPacket (int sock, struct nsdp_cmd *nc, List *attr, const struct time
                    (nc->remote_addr.sin_port != 0 && remote.sin_port != nc->remote_addr.sin_port) ||
                    len < (int)sizeof(struct nsdp_header) ||
                    !extractNsdpHeader(np.nh, nc) ||
-                   extractPacketAttributes(&np, attr, nc->ports) < 0)
+                   extractPacketAttributes(&np, attr) < 0)
                        continue;
                
                nc->remote_addr = remote;
diff --git a/raw/src/packet.c b/raw/src/packet.c
new file mode 100644 (file)
index 0000000..c9ac718
--- /dev/null
@@ -0,0 +1,159 @@
+
+#include <string.h>
+#include <errno.h>
+
+#include <nsdp/attr.h>
+#include <nsdp/packet.h>
+
+
+void initNsdpHeader (struct nsdp_header *nh, const struct nsdp_cmd *nc)
+{
+       memset(nh, 0, sizeof(struct nsdp_header));
+       nh->version = NSDP_VERSION;
+       nh->code = nc->code;
+       nh->error = nc->error;
+       nh->attr = htons(nc->attr_error);
+       
+       memcpy(nh->client_mac, &nc->client_mac, ETH_ALEN);
+       memcpy(nh->switch_mac, &nc->switch_mac, ETH_ALEN);
+       
+       nh->seqnum = htonl(nc->seqnum);
+       memcpy(nh->proto_id, NSDP_PROTOID, 4);
+}
+
+
+bool extractNsdpHeader (const struct nsdp_header *nh, struct nsdp_cmd *nc)
+{
+       unsigned int i;
+       
+       
+       if (nh->version != NSDP_VERSION)
+               return false;
+       
+       if (nc->code > 0 && nh->code != nc->code)
+               return false;
+       nc->code = nh->code;
+       
+       nc->error = nh->error;
+       nc->attr_error = ntohs(nh->attr);
+       
+       if (nh->unk1 != 0)
+               return false;
+       
+       if (*(unsigned short*)nh->unk2 != 0)
+               return false;
+       
+       for (i = 0; i < ETH_ALEN && nc->client_mac.ether_addr_octet[i] == 0; i++);
+       if (i < ETH_ALEN && memcmp(nh->client_mac, &nc->client_mac, ETH_ALEN) != 0)
+               return false;
+       memcpy(&nc->client_mac, nh->client_mac, ETH_ALEN);
+       
+       for (i = 0; i < ETH_ALEN && nc->switch_mac.ether_addr_octet[i] == 0; i++);
+       if (i < ETH_ALEN && memcmp(nh->switch_mac, &nc->switch_mac, ETH_ALEN) != 0)
+               return false;
+       memcpy(&nc->switch_mac, nh->switch_mac, ETH_ALEN);
+       
+       if (nc->seqnum > 0 && ntohl(nh->seqnum) != nc->seqnum)
+               return false;
+       nc->seqnum = ntohl(nh->seqnum);
+       
+       if (memcmp(nh->proto_id, NSDP_PROTOID, 4) != 0)
+               return false;
+       
+       if (*(unsigned int*)nh->unk3 != 0)
+               return false;
+       
+       return true;
+}
+
+
+int addPacketAttributes (struct nsdp_packet *np, const List* attr)
+{
+       ListNode *ln;
+       struct attr *at;
+       
+       
+       if (attr == NULL)
+               return 0;
+       
+       for (ln = attr->first; ln != NULL; ln = ln->next) {
+               at = ln->data;
+               
+               /* encode attribute data */
+               if (encodeAttr(at) < 0)
+                       return -EINVAL;
+               
+               /* attribute data bigger than the remaining size: error */
+               if ((int)(getPacketTotalSize(np) + sizeof(struct attr_header) + at->size) > np->maxlen)
+                       return -EMSGSIZE;
+               
+               /* set attribute code and size */
+               np->ah->attr = htons(at->attr);
+               np->ah->size = htons(at->size);
+               
+               /* copy attribute data */
+               if (at->size > 0 && at->data != NULL)
+                       memcpy(np->ah->data, at->data, at->size);
+               
+               /* move to next attribute */
+               np->ah = (struct attr_header*)(np->ah->data + at->size);
+       }
+       
+       
+       return 0;
+}
+
+
+int extractPacketAttributes (struct nsdp_packet *np, List *attr)
+{
+       struct attr *at;
+       unsigned short size;
+       
+       
+       while (getPacketTotalSize(np) < np->maxlen) {
+               /* no room for an attribute header: error */
+               if (getPacketTotalSize(np) + (int)sizeof(struct attr_header) > np->maxlen)
+                       return -EMSGSIZE;
+               
+               /* create new attribute */
+               size = ntohs(np->ah->size);
+               at = newAttr(ntohs(np->ah->attr), size, NULL);
+               if (at == NULL)
+                       return -ENOMEM;
+               
+               /* attribute data bigger than the remaining size: error */
+               if (getPacketTotalSize(np) + (int)sizeof(struct attr_header) + size > np->maxlen) {
+                       free(at);
+                       return -EMSGSIZE;
+               }
+               
+               /* copy attribute raw data */
+               if (size == 0) {
+                       at->data = NULL;
+               } else {
+                       at->data = malloc(size * sizeof(unsigned char));
+                       memcpy(at->data, np->ah->data, size);
+               }
+               
+               /* decode attribute data */
+               if(decodeAttr(at) == 0) {
+                       /* stop on an END attribute */
+                       if (at->attr == ATTR_END) {
+                               free(at);
+                               break;
+                       } else {
+                               pushBackList(attr, at);
+                       }
+               } else {
+                       free(at);
+               }
+               
+               /* move to next attribute */
+               np->ah = (struct attr_header*)(np->ah->data + size);
+       }
+       
+       
+       return 0;
+}
+
+