Changed indentation rules.
Move attributes encoding and decoding in a separate file.
Reorganized functions and declarations in two groups: low and high level.
#include <stdbool.h>
#include <arpa/inet.h>
+
#include <netinet/ether.h>
* This enum lists all the error codes the library can return to user.
**/
enum {
- ERR_OK=0, /**< no error */
- ERR_NET=-1, /**< network error */
- ERR_NOTLOG=-2, /**< not logged */
- ERR_DENIED=-3, /**< access denied */
- ERR_BADPASS=-4, /**< bad password */
- ERR_BADID=-5, /**< bad switch id */
- ERR_INVARG=-6, /**< invalid argument */
- ERR_TIMEOUT=-7, /**< timeout */
- ERR_NOTIMPL=-8 /**< not implemented */
+ ERR_OK = 0, /**< no error */
+ ERR_NET = -1, /**< network error */
+ ERR_NOTLOG = -2, /**< not logged */
+ ERR_DENIED = -3, /**< access denied */
+ ERR_BADPASS = -4, /**< bad password */
+ ERR_BADID = -5, /**< bad switch id */
+ ERR_INVARG = -6, /**< invalid argument */
+ ERR_TIMEOUT = -7, /**< timeout */
+ ERR_MEM = -8, /**< out of memory */
+ ERR_NOTIMPL = -8 /**< not implemented */
};
* This enum lists all the speeds a port can have.
**/
enum {
- SPEED_DOWN=0, /**< link down */
- SPEED_10=1, /**< 10 Mb/s */
- SPEED_100=4, /**< 100 Mb/s */
- SPEED_1000=5 /**< 1000 Mb/s */
+ SPEED_UNK = -1, /**< unknown status */
+ SPEED_DOWN = 0, /**< link down */
+ SPEED_10 = 1, /**< 10 Mb/s */
+ SPEED_100 = 4, /**< 100 Mb/s */
+ SPEED_1000 = 5 /**< 1000 Mb/s */
};
* This enum lists all the VLAN types available
**/
enum {
- VLAN_DISABLED=0, /**< VLAN disabled */
- VLAN_PORT_BASIC=1, /**< port basic */
- VLAN_PORT_ADV=2, /**< port advanced */
- VLAN_DOT_BASIC=3, /**< 802.1q basic */
- VLAN_DOT_ADV=4 /**< 802.1q advanced */
+ VLAN_DISABLED = 0, /**< VLAN disabled */
+ VLAN_PORT_BASIC = 1, /**< port basic */
+ VLAN_PORT_ADV = 2, /**< port advanced */
+ VLAN_DOT_BASIC = 3, /**< 802.1q basic */
+ VLAN_DOT_ADV = 4 /**< 802.1q advanced */
};
* This enum lists all the VLAN specifications a port can have.
**/
enum {
- VLAN_UNSPEC=0xFF, /**< unspecified */
- VLAN_NO=0, /**< not present */
- VLAN_UNTAGGED=1, /**< present, untagged */
- VLAN_TAGGED=2 /**< present, tagged */
+ VLAN_UNSPEC = 0xFF, /**< unspecified */
+ VLAN_NO = 0, /**< not present */
+ VLAN_UNTAGGED = 1, /**< present, untagged */
+ VLAN_TAGGED = 2 /**< present, tagged */
};
* This enum lists all the availables QoS modes.
**/
enum {
- QOS_PORT=1, /**< port based */
- QOS_DOT=2 /**< 802.1p based */
+ QOS_PORT = 1, /**< port based */
+ QOS_DOT = 2 /**< 802.1p based */
};
* This enum lists all the priorities a port can have.
**/
enum {
- PRIO_UNSPEC=-1, /**< unspecified */
- PRIO_HIGH=1, /**< high */
- PRIO_MED=2, /**< medium */
- PRIO_NORM=3, /**< normal */
- PRIO_LOW=4 /**< low */
+ PRIO_UNSPEC = -1, /**< unspecified */
+ PRIO_HIGH = 1, /**< high */
+ PRIO_MED = 2, /**< medium */
+ PRIO_NORM = 3, /**< normal */
+ PRIO_LOW = 4 /**< low */
};
* This enum lists all the available bitrates.
**/
enum {
- BITRATE_UNSPEC=-1, /**< unspecified */
- BITRATE_NOLIMIT=0, /**< unlimited */
- BITRATE_512K=1, /**< 512 Kb/s */
- BITRATE_1M=2, /**< 1 Mb/s */
- BITRATE_2M=3, /**< 2 Mb/s */
- BITRATE_4M=4, /**< 4 Mb/s */
- BITRATE_8M=5, /**< 8 Mb/s */
- BITRATE_16M=6, /**< 16 Mb/s */
- BITRATE_32M=7, /**< 32 Mb/s */
- BITRATE_64M=8, /**< 64 Mb/s */
- BITRATE_128M=9, /**< 128 Mb/s */
- BITRATE_256M=10, /**< 256 Mb/s */
- BITRATE_512M=11 /**< 512 Mb/s */
+ BITRATE_UNSPEC = -1, /**< unspecified */
+ BITRATE_NOLIMIT = 0, /**< unlimited */
+ BITRATE_512K = 1, /**< 512 Kb/s */
+ BITRATE_1M = 2, /**< 1 Mb/s */
+ BITRATE_2M = 3, /**< 2 Mb/s */
+ BITRATE_4M = 4, /**< 4 Mb/s */
+ BITRATE_8M = 5, /**< 8 Mb/s */
+ BITRATE_16M = 6, /**< 16 Mb/s */
+ BITRATE_32M = 7, /**< 32 Mb/s */
+ BITRATE_64M = 8, /**< 64 Mb/s */
+ BITRATE_128M = 9, /**< 128 Mb/s */
+ BITRATE_256M = 10, /**< 256 Mb/s */
+ BITRATE_512M = 11 /**< 512 Mb/s */
};
* Represents the network configuration of a switch.
*/
struct net_conf {
- struct in_addr ip; /**< IP */
- struct in_addr netmask; /**< netmask */
- struct in_addr gw; /**< gateway IP */
- bool dhcp; /**< DHCP enabled */
+ struct in_addr ip; /**< IP */
+ struct in_addr netmask; /**< netmask */
+ struct in_addr gw; /**< gateway IP */
+ bool dhcp; /**< DHCP enabled */
};
* Represents the main characteristics of a switch.
*/
struct swi_attr {
- char product[PRODUCT_SIZE]; /**< product name (eg.\ GS108EV1) */
- char name[NAME_SIZE]; /**< custom name */
- char firmware[FIRMWARE_SIZE]; /**< firmware version string */
- unsigned char ports; /**< number of ports */
- struct ether_addr mac; /**< MAC address */
- struct net_conf nc; /**< network configuration */
+ char product[PRODUCT_SIZE]; /**< product name (eg.\ GS108EV1) */
+ char name[NAME_SIZE]; /**< custom name */
+ char firmware[FIRMWARE_SIZE]; /**< firmware version string */
+ unsigned char ports; /**< number of ports */
+ struct ether_addr mac; /**< MAC address */
+ struct net_conf nc; /**< network configuration */
};
* Represents statistics of a particular port.
*/
struct port_stats {
- unsigned long long recv; /**< packets received */
- unsigned long long sent; /**< packets sent */
- unsigned long long crc; /**< CRC errors */
+ unsigned long long recv; /**< packets received */
+ unsigned long long sent; /**< packets sent */
+ unsigned long long crc; /**< CRC errors */
};
* Represents the IGMP snooping configuration of a switch.
*/
struct igmp_conf {
- bool enable; /**< IGMP snooping enabled */
- unsigned short vlan; /**< VLAN on which IGMP snooping is done */
- bool validate; /**< validate IGMPv3 headers */
- bool block; /**< block unknown multicast addresses */
+ bool enable; /**< IGMP snooping enabled */
+ unsigned short vlan; /**< VLAN on which IGMP snooping is done */
+ bool validate; /**< validate IGMPv3 headers */
+ bool block; /**< block unknown multicast addresses */
};
* Cabletest result.
*/
struct cabletest {
- char port; /**< port */
- int v1; /**< raw value 1 */
- int v2; /**< raw value 2 */
+ char port; /**< port */
+ int v1; /**< raw value 1 */
+ int v2; /**< raw value 2 */
};
--- /dev/null
+
+#include <ngadmin.h>
+
+#include "lib.h"
+#include "attr.h"
+#include "protocol.h"
+
+
+#define ATTR_HANDLER_ENTRY(at, sz, enc, dec) {.attr = at, .size = sz, .encode = enc, .decode = dec}
+
+
+
+static bool bool_endecode (struct attr *at, unsigned char ports UNUSED)
+{
+ *(char*)at->data = (*(char*)at->data != 0);
+
+ return true;
+}
+
+
+static bool ports_status_decode (struct attr *at, unsigned char ports)
+{
+ struct attr_port_status *ps = at->data;
+
+ if (ps->port < 1 || ps->port > ports)
+ return false;
+
+ switch (ps->status) {
+ case SPEED_DOWN:
+ case SPEED_10:
+ case SPEED_100:
+ case SPEED_1000:
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+
+static bool port_stat_decode (struct attr *at, unsigned char ports)
+{
+ struct attr_port_stat *ps = at->data;
+ unsigned long long *v;
+
+ if (ps->port < 1 || ps->port > ports)
+ return false;
+
+ for (v = &ps->recv; ((char*)v) - ((char*)ps) < (int)sizeof(struct attr_port_stat); v++)
+ *v = be64toh(*v);
+
+
+ return true;
+}
+
+
+static bool bitrate_decode (struct attr *at, unsigned char ports)
+{
+ struct attr_bitrate *sb = at->data;
+
+ if (sb->port < 1 || sb->port > ports)
+ return false;
+
+ sb->bitrate = ntohl(sb->bitrate);
+ if (sb->bitrate < BITRATE_UNSPEC || sb->bitrate > BITRATE_512M)
+ return false;
+
+ return true;
+}
+
+
+static bool bitrate_encode (struct attr *at, unsigned char ports)
+{
+ struct attr_bitrate *sb = at->data;
+
+ if (sb->port < 1 || sb->port > ports)
+ return false;
+
+ if (sb->bitrate < BITRATE_UNSPEC || sb->bitrate > BITRATE_512M)
+ return false;
+ sb->bitrate = htonl(sb->bitrate);
+
+ return true;
+}
+
+
+static bool qos_mode_endecode (struct attr *at, unsigned char ports UNUSED)
+{
+ unsigned char v = *(char*)at->data;
+
+ return (v == QOS_PORT || v == QOS_DOT);
+}
+
+
+static bool qos_endecode (struct attr *at, unsigned char ports)
+{
+ struct attr_qos *aq = at->data;
+
+ if (aq->port < 1 || aq->port > ports)
+ return false;
+
+ return (aq->prio >= PRIO_HIGH && aq->prio <= PRIO_LOW);
+}
+
+
+static bool pvid_decode (struct attr *at, unsigned char ports)
+{
+ struct attr_pvid *ap= at->data;
+
+ if (ap->port < 1 || ap->port > ports)
+ return false;
+
+ ap->vlan = ntohs(ap->vlan);
+
+ return (ap->vlan >= VLAN_MIN && ap->vlan <= VLAN_MAX);
+}
+
+
+static bool pvid_encode (struct attr *at, unsigned char ports)
+{
+ struct attr_pvid *ap= at->data;
+
+ if (ap->port < 1 || ap->port > ports)
+ return false;
+
+ if (ap->vlan < VLAN_MIN || ap->vlan > VLAN_MAX)
+ return false;
+
+ ap->vlan = htons(ap->vlan);
+
+ return true;
+}
+
+
+static bool vlan_destroy_encode (struct attr *at, unsigned char ports UNUSED)
+{
+ unsigned short v = *(unsigned short*)at->data;
+
+ if (v < VLAN_MIN || v > VLAN_MAX)
+ return false;
+
+ *(unsigned short*)at->data = htons(v);
+
+ return true;
+}
+
+
+static bool mirror_decode (struct attr *at, unsigned char ports)
+{
+ unsigned char *r = at->data, *p;
+ int port;
+
+
+ if (at->size != 3 + ((ports - 1) >> 3))
+ return false;
+
+ /* r[0] == 0 is allowed and means mirroring is disabled */
+ if (r[0] > ports)
+ return false;
+
+ p = malloc(1 + ports);
+ if (p == NULL)
+ return false;
+
+ memset(p, 0, 1 + ports);
+
+ if (r[0] == 0)
+ goto end;
+
+ p[0] = r[0];
+
+ for (port = 1; port <= ports; port++)
+ p[port] = (r[2] >> (8 - port)) & 1; /* FIXME: if ports > 8 */
+
+end:
+ free(at->data);
+ at->data = p;
+ at->size = 1 + ports;
+
+
+ return true;
+}
+
+
+static bool mirror_encode (struct attr *at, unsigned char ports)
+{
+ unsigned char *p = at->data, *r;
+ int port;
+
+
+ if (at->size != 1 + ports)
+ return false;
+
+ /* p[0] == 0 is allowed and means mirroring is disabled */
+ if (p[0] > ports)
+ return false;
+
+ r = malloc(3 + ((ports - 1) >> 3));
+ if (r == NULL)
+ return false;
+
+ memset(r, 0, 3 + ((ports - 1) >> 3));
+
+ if (p[0] == 0)
+ goto end;
+
+ r[0] = p[0];
+
+ for (port = 1; port <= ports; port++) {
+ if (p[0] != port)
+ r[2] |= (p[port] & 1) << (8 - port); /* FIXME: if ports > 8 */
+ }
+
+end:
+ free(at->data);
+ at->data = r;
+ at->size = 3 + ((ports - 1) >> 3);
+
+
+ return true;
+}
+
+
+static bool igmp_vlan_decode (struct attr *at, unsigned char ports UNUSED)
+{
+ struct attr_igmp_vlan *aiv = at->data;
+
+ aiv->enable = ntohs(aiv->enable);
+ if (aiv->enable != 0 && aiv->enable != 1)
+ return false;
+
+ aiv->vlan = ntohs(aiv->vlan);
+ if (aiv->vlan < VLAN_MIN || aiv->vlan > VLAN_MAX)
+ return false;
+
+ return true;
+}
+
+
+static bool igmp_vlan_encode (struct attr *at, unsigned char ports UNUSED)
+{
+ struct attr_igmp_vlan *aiv = at->data;
+
+ if (aiv->enable != 0 && aiv->enable != 1)
+ return false;
+ aiv->enable = htons(aiv->enable);
+
+ if (aiv->vlan < VLAN_MIN || aiv->vlan > VLAN_MAX)
+ return false;
+ aiv->vlan = htons(aiv->vlan);
+
+ return true;
+}
+
+
+static bool cabletest_do_encode (struct attr *at, unsigned char ports)
+{
+ struct attr_cabletest_do *acd = at->data;
+
+ if (acd->port < 1 || acd->port > ports)
+ return false;
+
+ return (acd->action == 1);
+}
+
+
+static bool cabletest_result_encode (struct attr *at, unsigned char ports)
+{
+ unsigned char v = *(unsigned char*)at->data;
+
+ return (v >= 1 && v <= ports);
+}
+
+
+static bool cabletest_result_decode (struct attr *at, unsigned char ports)
+{
+ struct attr_cabletest_result *acr = at->data;
+
+ if (acr->port < 1 || acr->port > ports)
+ return false;
+
+ acr->v1 = ntohl(acr->v1);
+ acr->v2 = ntohl(acr->v2);
+
+ return true;
+}
+
+
+static bool cabletest_result_endecode (struct attr *at, unsigned char ports)
+{
+ switch (at->size) {
+
+ case 1:
+ return cabletest_result_encode(at, ports);
+
+ case sizeof(struct attr_cabletest_result):
+ return cabletest_result_decode(at, ports);
+
+ default:
+ return false;
+ }
+}
+
+
+static bool vlan_type_endecode (struct attr *at, unsigned char ports UNUSED)
+{
+ char v = *(char*)at->data;
+
+ return (v >= VLAN_DISABLED && v <= VLAN_DOT_ADV);
+}
+
+
+static bool vlan_dot_decode (struct attr *at, unsigned char ports)
+{
+ char *r = at->data;
+ struct attr_vlan_dot *avd;
+ int port;
+
+
+ if (at->size != (2 + 2 * (1 + ((ports - 1) >> 3))))
+ return false;
+
+ avd = malloc(sizeof(struct attr_vlan_dot) + ports);
+ if (avd == NULL)
+ return false;
+
+ avd->vlan = ntohs(*(unsigned short*)r);
+ r += 2;
+
+ for (port = 0; port < ports; port++) {
+ /* FIXME: if ports > 8 */
+ if ((r[1] >> (7 - port)) & 1)
+ avd->ports[port] = VLAN_TAGGED;
+ else if ((r[0] >> (7 - port)) & 1)
+ avd->ports[port] = VLAN_UNTAGGED;
+ else
+ avd->ports[port] = VLAN_NO;
+ }
+
+ free(at->data);
+ at->data = avd;
+ at->size = sizeof(struct attr_vlan_dot) + ports;
+
+
+ return true;
+}
+
+
+static bool vlan_dot_encode (struct attr *at, unsigned char ports)
+{
+ struct attr_vlan_dot *avd = at->data;
+ char *r, fl;
+ unsigned int size, port;
+
+
+ if (avd->vlan < VLAN_MIN || avd->vlan > VLAN_MAX)
+ return false;
+
+ /* just a header is valid */
+ if (at->size == sizeof(struct attr_vlan_dot))
+ size = 2;
+ else if (at->size == sizeof(struct attr_vlan_dot) + ports)
+ size = (2 + 2 * (1 + ((ports - 1) >> 3)));
+ else
+ return false;
+
+ r = malloc(size);
+ if (r == NULL)
+ return false;
+
+ memset(r, 0, size);
+ *(unsigned short*)r = htons(avd->vlan);
+
+ if (size == 2)
+ goto end;
+
+ r += 2;
+
+ for (port = 0; port < ports; port++) {
+ /* FIXME: if ports > 8 */
+ fl = (1 << (7 - port));
+ switch (avd->ports[port]) {
+ case VLAN_TAGGED:
+ r[1] |= fl;
+ case VLAN_UNTAGGED:
+ r[0] |= fl;
+ }
+ }
+
+ r -= 2;
+
+end:
+ free(at->data);
+ at->data = r;
+ at->size = size;
+
+
+ return true;
+}
+
+
+
+/* WARNING: attributes codes MUST be in ascending order */
+static const struct attr_handler attrtab[] = {
+ ATTR_HANDLER_ENTRY(ATTR_MAC, 6, NULL, NULL),
+ ATTR_HANDLER_ENTRY(ATTR_IP, 4, NULL, NULL),
+ ATTR_HANDLER_ENTRY(ATTR_NETMASK, 4, NULL, NULL),
+ ATTR_HANDLER_ENTRY(ATTR_GATEWAY, 4, NULL, NULL),
+ ATTR_HANDLER_ENTRY(ATTR_DHCP, 2, NULL, NULL),
+ ATTR_HANDLER_ENTRY(ATTR_RESTART, 1, NULL, NULL),
+ ATTR_HANDLER_ENTRY(ATTR_DEFAULTS, 1, NULL, NULL),
+ ATTR_HANDLER_ENTRY(ATTR_PORT_STATUS, sizeof(struct attr_port_status), NULL, ports_status_decode),
+ ATTR_HANDLER_ENTRY(ATTR_PORT_STATISTICS, sizeof(struct attr_port_stat), NULL, port_stat_decode),
+ ATTR_HANDLER_ENTRY(ATTR_STATS_RESET, 1, bool_endecode, bool_endecode),
+ ATTR_HANDLER_ENTRY(ATTR_CABLETEST_DO, sizeof(struct attr_cabletest_do), cabletest_do_encode, NULL),
+ ATTR_HANDLER_ENTRY(ATTR_CABLETEST_RESULT, 0, cabletest_result_endecode, cabletest_result_endecode),
+ ATTR_HANDLER_ENTRY(ATTR_VLAN_TYPE, 1, vlan_type_endecode, vlan_type_endecode),
+ ATTR_HANDLER_ENTRY(ATTR_VLAN_DOT_CONF, 0, vlan_dot_encode, vlan_dot_decode),
+ ATTR_HANDLER_ENTRY(ATTR_VLAN_DESTROY, 2, vlan_destroy_encode, NULL),
+ ATTR_HANDLER_ENTRY(ATTR_VLAN_PVID, sizeof(struct attr_pvid), pvid_encode, pvid_decode),
+ ATTR_HANDLER_ENTRY(ATTR_QOS_TYPE, 1, qos_mode_endecode, qos_mode_endecode),
+ ATTR_HANDLER_ENTRY(ATTR_QOS_CONFIG, sizeof(struct attr_qos), qos_endecode, qos_endecode),
+ ATTR_HANDLER_ENTRY(ATTR_BITRATE_INPUT, sizeof(struct attr_bitrate), bitrate_encode, bitrate_decode),
+ ATTR_HANDLER_ENTRY(ATTR_BITRATE_OUTPUT, sizeof(struct attr_bitrate), bitrate_encode, bitrate_decode),
+ ATTR_HANDLER_ENTRY(ATTR_STORM_ENABLE, 1, bool_endecode, bool_endecode),
+ ATTR_HANDLER_ENTRY(ATTR_STORM_BITRATE, sizeof(struct attr_bitrate), bitrate_encode, bitrate_decode),
+ ATTR_HANDLER_ENTRY(ATTR_MIRROR, 0, mirror_encode, mirror_decode),
+ ATTR_HANDLER_ENTRY(ATTR_PORTS_COUNT, 1, NULL, NULL),
+ ATTR_HANDLER_ENTRY(ATTR_IGMP_ENABLE_VLAN, sizeof(struct attr_igmp_vlan), igmp_vlan_encode, igmp_vlan_decode),
+ ATTR_HANDLER_ENTRY(ATTR_IGMP_BLOCK_UNK, 1, bool_endecode, bool_endecode),
+ ATTR_HANDLER_ENTRY(ATTR_IGMP_VALID_V3, 1, bool_endecode, bool_endecode)
+};
+
+
+
+const struct attr_handler* getAttrHandler (unsigned short attrcode)
+{
+ const struct attr_handler *ah;
+ const unsigned int tab_size = sizeof(attrtab) / sizeof(struct attr_handler);
+ unsigned int inf, sup, index;
+
+
+ inf = 0;
+ sup = tab_size;
+ index = tab_size >> 1;
+ while (index < sup) {
+ ah = &attrtab[index];
+
+ if (ah->attr > attrcode) {
+ sup = index;
+ index -= ((index - inf) >> 1) + ((index - inf) & 1);
+ } else if (ah->attr < attrcode) {
+ inf = index;
+ index += ((sup - index) >> 1) + ((sup - index) & 1);
+ } else {
+ return ah;
+ }
+ }
+
+
+ return NULL;
+}
+
+
--- /dev/null
+
+#ifndef DEF_ATTR
+#define DEF_ATTR
+
+
+#include <stdbool.h>
+
+#include "protocol.h"
+
+
+#define ATTR_PRODUCT 0x0001
+#define ATTR_UNK_0002 0x0002
+#define ATTR_NAME 0x0003
+#define ATTR_MAC 0x0004
+#define ATTR_UNK_0005 0x0005
+#define ATTR_IP 0x0006
+#define ATTR_NETMASK 0x0007
+#define ATTR_GATEWAY 0x0008
+#define ATTR_NEW_PASSWORD 0x0009
+#define ATTR_PASSWORD 0x000A
+#define ATTR_DHCP 0x000B
+#define ATTR_UNK_000C 0x000C
+#define ATTR_FIRM_VER 0x000D
+#define ATTR_UNK_000E 0x000E
+#define ATTR_UNK_000F 0x000F
+#define ATTR_FIRM_UPGRADE 0x0010
+#define ATTR_RESTART 0x0013
+#define ATTR_DEFAULTS 0x0400
+#define ATTR_PORT_STATUS 0x0C00
+#define ATTR_PORT_STATISTICS 0x1000
+#define ATTR_STATS_RESET 0x1400
+#define ATTR_CABLETEST_DO 0x1800
+#define ATTR_CABLETEST_RESULT 0x1C00
+#define ATTR_VLAN_TYPE 0x2000
+#define ATTR_VLAN_PORT_CONF 0x2400
+#define ATTR_VLAN_DOT_CONF 0x2800
+#define ATTR_VLAN_DESTROY 0x2C00
+#define ATTR_VLAN_PVID 0x3000
+#define ATTR_QOS_TYPE 0x3400
+#define ATTR_QOS_CONFIG 0x3800
+#define ATTR_BITRATE_INPUT 0x4C00
+#define ATTR_BITRATE_OUTPUT 0x5000
+#define ATTR_STORM_ENABLE 0x5400
+#define ATTR_STORM_BITRATE 0x5800
+#define ATTR_MIRROR 0x5C00
+#define ATTR_PORTS_COUNT 0x6000
+#define ATTR_MAX_VLAN 0x6400
+#define ATTR_IGMP_ENABLE_VLAN 0x6800
+#define ATTR_IGMP_BLOCK_UNK 0x6C00
+#define ATTR_IGMP_VALID_V3 0x7000
+#define ATTR_TLV_BITMAP 0x7400
+#define ATTR_END 0xFFFF
+
+#define UNUSED __attribute__((unused))
+
+
+struct attr_handler {
+ unsigned short attr; /* attribute code */
+ unsigned int size; /* expected data size */
+ bool (*encode)(struct attr *at, unsigned char ports); /* encode function */
+ bool (*decode)(struct attr *at, unsigned char ports); /* decode function */
+};
+
+
+const struct attr_handler* getAttrHandler (unsigned short attrcode);
+
+
+
+
+struct attr_port_status {
+ unsigned char port;
+ unsigned char status;
+ unsigned char unk;
+} __attribute__((packed));
+
+
+struct attr_port_stat {
+ unsigned char port;
+ unsigned long long recv;
+ unsigned long long sent;
+ unsigned long long unk1;
+ unsigned long long unk2;
+ unsigned long long unk3;
+ unsigned long long crc;
+} __attribute__((packed));
+
+
+struct attr_bitrate {
+ unsigned char port;
+ int bitrate;
+} __attribute__((packed));
+
+
+struct attr_qos {
+ unsigned char port;
+ unsigned char prio;
+} __attribute__((packed));
+
+
+struct attr_pvid {
+ unsigned char port;
+ unsigned short vlan;
+} __attribute__((packed));
+
+
+struct attr_igmp_vlan {
+ unsigned short enable;
+ unsigned short vlan;
+} __attribute__((packed));
+
+
+struct attr_cabletest_do {
+ unsigned char port;
+ unsigned char action;
+} __attribute__((packed));
+
+
+struct attr_cabletest_result {
+ unsigned char port;
+ unsigned int v1;
+ unsigned int v2;
+} __attribute__((packed));
+
+
+struct attr_vlan_dot {
+ unsigned short vlan;
+ unsigned char ports[0];
+};
+
+
+#endif
+
#define DEF_LIB
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
+#include <arpa/inet.h>
+
#include <net/if.h>
+#include <netinet/ether.h>
#include <ngadmin.h>
-#define PASSWORD_MAX 32
-
-
-#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
-
-#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 PASSWORD_MAX 32
struct ngadmin {
- // network
- int sock; // socket
- struct sockaddr_in local; // local address & port
- struct in_addr brd; // broadcast address
- char iface[IFNAMSIZ]; // interface
- struct timeval timeout; // timeout
- struct ether_addr localmac; // local MAC address
- bool keepbroad; // keep broadcasting
- bool globalbroad; // use global broadcast address (255.255.255.255)
- //
- char password[PASSWORD_MAX]; // password to use to login on switches
- struct swi_attr *swi_tab; // array of detected switches
- int swi_count; // number of detected switches
- struct swi_attr *current; // administred switch
- int seq; // sequence number for packets
+ /* network */
+ int sock; /* socket */
+ struct sockaddr_in local; /* local address & port */
+ struct in_addr brd; /* broadcast address */
+ char iface[IFNAMSIZ]; /* interface */
+ struct timeval timeout; /* timeout */
+ struct ether_addr localmac; /* local MAC address */
+ bool keepbroad; /* keep broadcasting */
+ bool globalbroad; /* use global broadcast address (255.255.255.255) */
+ /* switch properties */
+ char password[PASSWORD_MAX]; /* password to use to login on switches */
+ struct swi_attr *swi_tab; /* array of detected switches */
+ int swi_count; /* number of detected switches */
+ struct swi_attr *current; /* administred switch */
+ int seq; /* sequence number for packets */
};
-
#endif
-#include "network.h"
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <netinet/ether.h>
+#include <sys/ioctl.h>
+#include "attr.h"
+#include "protocol.h"
+#include "network.h"
-// -----------------------------------
-int startNetwork (struct ngadmin *nga) {
-
- struct ifreq ifr;
- int ret;
-
-
- // create socket
- if ( (nga->sock=socket(AF_INET, SOCK_DGRAM, 0))<0 ) {
- perror("socket");
- return nga->sock;
- }
-
- memset(&ifr, 0, sizeof(struct ifreq));
- strncpy(ifr.ifr_name, nga->iface, IFNAMSIZ-1);
-
- // get the interface broadcast address
- if ( (ret=ioctl(nga->sock, SIOCGIFBRDADDR, &ifr))<0 ) {
- perror("ioctl(SIOCGIFBRDADDR)");
- close(nga->sock);
- return ret;
- }
- nga->brd=(*(struct sockaddr_in*)&ifr.ifr_addr).sin_addr;
-
- // get the interface MAC address
- if ( (ret=ioctl(nga->sock, SIOCGIFHWADDR, &ifr))<0 ) {
- perror("ioctl(SIOCGIFHWADDR)");
- close(nga->sock);
- return ret;
- }
- memcpy(&nga->localmac, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
-
- // bind
- memset(&nga->local, 0, sizeof(struct sockaddr_in));
- nga->local.sin_family=AF_INET;
- nga->local.sin_port=htons(CLIENT_PORT);
-
- if ( (ret=bind(nga->sock, (struct sockaddr*)&nga->local, sizeof(struct sockaddr_in)))<0 ) {
- perror("bind");
- close(nga->sock);
- return ret;
- }
-
- // allow broadcasting
- ret=1;
- if ( (ret=setsockopt(nga->sock, SOL_SOCKET, SO_BROADCAST, &ret, sizeof(ret)))<0 ) {
- perror("setsockopt(SO_BROADCAST)");
- return ret;
- }
-
- // prevent unicast packets from being routed by setting the TTL to 1
- ret=1;
- if ( (ret=setsockopt(nga->sock, IPPROTO_IP, IP_TTL, &ret, sizeof(ret)))<0 ) {
- perror("setsockopt(IP_TTL)");
- return ret;
- }
-
-
- return 0;
-
+int startNetwork (struct ngadmin *nga)
+{
+ struct ifreq ifr;
+ int ret;
+
+
+ /* create socket */
+ nga->sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (nga->sock < 0) {
+ perror("socket");
+ return nga->sock;
+ }
+
+ memset(&ifr, 0, sizeof(struct ifreq));
+ strncpy(ifr.ifr_name, nga->iface, IFNAMSIZ - 1);
+
+ /* get the interface broadcast address */
+ ret = ioctl(nga->sock, SIOCGIFBRDADDR, &ifr);
+ if (ret < 0) {
+ perror("ioctl(SIOCGIFBRDADDR)");
+ close(nga->sock);
+ return ret;
+ }
+ nga->brd = (*(struct sockaddr_in*)&ifr.ifr_addr).sin_addr;
+
+ /* get the interface MAC address */
+ ret = ioctl(nga->sock, SIOCGIFHWADDR, &ifr);
+ if (ret < 0) {
+ perror("ioctl(SIOCGIFHWADDR)");
+ close(nga->sock);
+ return ret;
+ }
+ memcpy(&nga->localmac, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
+
+ /* bind */
+ memset(&nga->local, 0, sizeof(struct sockaddr_in));
+ nga->local.sin_family = AF_INET;
+ nga->local.sin_port = htons(CLIENT_PORT);
+
+ ret = bind(nga->sock, (struct sockaddr*)&nga->local, sizeof(struct sockaddr_in));
+ if (ret < 0) {
+ perror("bind");
+ close(nga->sock);
+ return ret;
+ }
+
+ /* allow broadcasting */
+ ret = 1;
+ ret = setsockopt(nga->sock, SOL_SOCKET, SO_BROADCAST, &ret, sizeof(ret));
+ if (ret < 0) {
+ perror("setsockopt(SO_BROADCAST)");
+ return ret;
+ }
+
+ /* prevent unicast packets from being routed by setting the TTL to 1 */
+ ret = 1;
+ ret = setsockopt(nga->sock, IPPROTO_IP, IP_TTL, &ret, sizeof(ret));
+ if (ret < 0) {
+ perror("setsockopt(IP_TTL)");
+ return ret;
+ }
+
+
+ return 0;
}
-
-// ----------------------------------
-int stopNetwork (struct ngadmin *nga) {
-
- return close(nga->sock);
-
+int stopNetwork (struct ngadmin *nga)
+{
+ return close(nga->sock);
}
-
-// -------------------------------------
-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.
- */
- if ( (ret=setsockopt(nga->sock, SOL_SOCKET, SO_BINDTODEVICE, nga->iface, strlen(nga->iface)+1))<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.
- */
- ret=1;
- if ( (ret=setsockopt(nga->sock, SOL_SOCKET, SO_DONTROUTE, &ret, sizeof(ret)))<0 ) {
- perror("setsockopt(SO_DONTROUTE)");
- return ret;
- }
-
-
- return 0;
-
+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.
+ */
+ 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.
+ */
+ ret = 1;
+ ret = setsockopt(nga->sock, SOL_SOCKET, SO_DONTROUTE, &ret, sizeof(ret));
+ if (ret <0) {
+ perror("setsockopt(SO_DONTROUTE)");
+ return ret;
+ }
+
+
+ return 0;
}
-
-// ------------------------------------
-int updateTimeout (struct ngadmin *nga) {
-
- int ret;
-
-
- // specify receive timeout
- if ( (ret=setsockopt(nga->sock, SOL_SOCKET, SO_RCVTIMEO, &nga->timeout, sizeof(struct timeval)))<0 ) {
- perror("setsockopt(SO_RCVTIMEO)");
- return ret;
- }
-
-
- return 0;
-
+int updateTimeout (struct ngadmin *nga)
+{
+ int ret;
+
+
+ /* specify receive timeout */
+ ret = setsockopt(nga->sock, SOL_SOCKET, SO_RCVTIMEO, &nga->timeout, sizeof(struct timeval));
+ if (ret < 0) {
+ perror("setsockopt(SO_RCVTIMEO)");
+ return ret;
+ }
+
+
+ return 0;
}
-
-// ----------------------------------------------------------------
-int sendNgPacket (struct ngadmin *nga, char code, const List *attr) {
-
- char buffer[1500];
- struct ng_packet np;
- ListNode *ln;
- struct attr *at;
- struct sockaddr_in remote;
- const struct swi_attr *sa=nga->current;
- int ret;
-
-
- np.buffer=buffer;
- np.maxlen=sizeof(buffer);
- initNgPacket(&np);
- initNgHeader(np.nh, code, &nga->localmac, sa==NULL ? NULL : &sa->mac , ++nga->seq);
-
- if ( attr!=NULL ) {
- for (ln=attr->first; ln!=NULL; ln=ln->next) {
- at=ln->data;
- addPacketAttr(&np, at->attr, at->size, at->data);
- }
- }
-
- memset(&remote, 0, sizeof(struct sockaddr_in));
- remote.sin_family=AF_INET;
- remote.sin_port=htons(SWITCH_PORT);
-
- if ( sa!=NULL && !nga->keepbroad ) remote.sin_addr=sa->nc.ip;
- else if ( nga->globalbroad ) remote.sin_addr.s_addr=htonl(INADDR_BROADCAST);
- else remote.sin_addr=nga->brd;
-
-
- if ( (ret=sendto(nga->sock, buffer, getPacketTotalSize(&np), 0, (struct sockaddr*)&remote, sizeof(struct sockaddr_in)))<0 ) {
- perror("sendto");
- }
-
-
- return ret;
-
+int sendNgPacket (struct ngadmin *nga, char code, const List *attr)
+{
+ char buffer[1500];
+ struct ng_packet np;
+ struct sockaddr_in remote;
+ const struct swi_attr *sa = nga->current;
+ int ret;
+
+
+ np.buffer = buffer;
+ np.maxlen = sizeof(buffer);
+ initNgPacket(&np);
+ initNgHeader(np.nh, code, &nga->localmac, sa == NULL ? NULL : &sa->mac, ++nga->seq);
+
+ ret = addPacketAttributes(&np, attr, sa == NULL ? 0 : sa->ports);
+ if (ret < 0)
+ return ret;
+
+ memset(&remote, 0, sizeof(struct sockaddr_in));
+ remote.sin_family = AF_INET;
+ remote.sin_port = htons(SWITCH_PORT);
+
+ /* destination address selection */
+ if (sa != NULL && !nga->keepbroad)
+ remote.sin_addr = sa->nc.ip;
+ else if (nga->globalbroad)
+ remote.sin_addr.s_addr = htonl(INADDR_BROADCAST);
+ else
+ remote.sin_addr = nga->brd;
+
+ ret = sendto(nga->sock, buffer, getPacketTotalSize(&np), 0, (struct sockaddr*)&remote, sizeof(struct sockaddr_in));
+ if (ret < 0)
+ perror("sendto");
+
+
+ return ret;
}
-
-// ------------------------------------------------------------------------------------------------------------
-int recvNgPacket (struct ngadmin *nga, char code, unsigned char *error, unsigned short *attr_error, List *attr) {
-
- char buffer[1500];
- struct ng_packet np;
- struct sockaddr_in remote;
- socklen_t slen=sizeof(struct sockaddr_in);
- const struct swi_attr *sa=nga->current;
- struct timeval rem;
- fd_set fs;
- int len=-1;
-
-
- np.buffer=buffer;
-
- memset(&remote, 0, sizeof(struct sockaddr_in));
- remote.sin_family=AF_INET;
-
- rem=nga->timeout;
-
- while ( 1 ) {
-
- FD_ZERO(&fs);
- FD_SET(nga->sock, &fs);
- select(nga->sock+1, &fs, NULL, NULL, &rem); // FIXME: non portable
-
- len=recvfrom(nga->sock, buffer, sizeof(buffer), MSG_DONTWAIT, (struct sockaddr*)&remote, &slen);
-
- if ( len<0 ) break;
-
- np.maxlen=len;
- initNgPacket(&np);
-
- if (
- ntohs(remote.sin_port)!=SWITCH_PORT ||
- len<(int)sizeof(struct ng_header) ||
- !validateNgHeader(np.nh, code, &nga->localmac, sa==NULL ? NULL : &sa->mac , nga->seq) ||
- extractPacketAttributes(&np, error, attr_error, attr)<0
- ) continue;
-
- len=0;
- break;
-
- }
-
-
- return len;
-
+int recvNgPacket (struct ngadmin *nga, char code, unsigned char *error, unsigned short *attr_error, List *attr, unsigned short filter_attr)
+{
+ char buffer[1500];
+ struct ng_packet np;
+ struct sockaddr_in remote;
+ socklen_t slen = sizeof(struct sockaddr_in);
+ const struct swi_attr *sa = nga->current;
+ struct timeval rem;
+ fd_set fs;
+ int len = -1;
+
+
+ np.buffer = buffer;
+
+ memset(&remote, 0, sizeof(struct sockaddr_in));
+ remote.sin_family = AF_INET;
+
+ rem = nga->timeout;
+
+ while (1) {
+
+ FD_ZERO(&fs);
+ FD_SET(nga->sock, &fs);
+ select(nga->sock+1, &fs, NULL, NULL, &rem); /* FIXME: non portable */
+
+ len = recvfrom(nga->sock, buffer, sizeof(buffer), MSG_DONTWAIT, (struct sockaddr*)&remote, &slen);
+
+ if (len < 0)
+ break;
+
+ np.maxlen = len;
+ initNgPacket(&np);
+
+ if (ntohs(remote.sin_port) != SWITCH_PORT ||
+ len < (int)sizeof(struct ng_header) ||
+ !validateNgHeader(np.nh, code, &nga->localmac, sa == NULL ? NULL : &sa->mac, nga->seq) ||
+ extractPacketAttributes(&np, error, attr_error, attr, filter_attr, sa == NULL ? 0 : sa->ports) < 0)
+ continue;
+
+ len = 0;
+ break;
+ }
+
+
+ return len;
}
-
-static int checkErrorCode (unsigned char err, unsigned short attr_error) {
-
-
- switch ( err ) {
-
- case ERROR_DENIED: return attr_error==ATTR_PASSWORD ? ERR_BADPASS : ERR_DENIED ;
- case ERROR_INVALID_VALUE: return ERR_INVARG;
- default: return ERR_OK;
-
- }
-
-
+static int checkErrorCode (unsigned char err, unsigned short attr_error)
+{
+ switch (err) {
+ case ERROR_DENIED:
+ return attr_error == ATTR_PASSWORD ? ERR_BADPASS : ERR_DENIED;
+ case ERROR_INVALID_VALUE:
+ return ERR_INVARG;
+ default:
+ return ERR_OK;
+ }
}
-
-// ----------------------------------------------
-int readRequest (struct ngadmin *nga, List *attr) {
-
- int i, ret=ERR_OK;
- unsigned char err;
- unsigned short attr_error;
-
-
- if ( nga==NULL ) {
- ret=ERR_INVARG;
- goto end;
- }
-
- // add end attribute to end
- pushBackList(attr, newEmptyAttr(ATTR_END));
-
- i=sendNgPacket(nga, CODE_READ_REQ, attr);
-
- // the list will be filled again by recvNgPacket
- clearList(attr, (void(*)(void*))freeAttr);
-
- if ( i<0 || (i=recvNgPacket(nga, CODE_READ_REP, &err, &attr_error, attr))<0 ) {
- ret= ( errno==EAGAIN || errno==EWOULDBLOCK ) ? ERR_TIMEOUT : ERR_NET ;
- goto end;
- }
-
-
- // check error code
- ret=checkErrorCode(err, attr_error);
-
-
- end:
-
- return ret;
-
+int readRequest (struct ngadmin *nga, List *attr, unsigned short filter_attr)
+{
+ int i, ret = ERR_OK;
+ unsigned char err;
+ unsigned short attr_error;
+
+
+ if (nga == NULL) {
+ ret = ERR_INVARG;
+ goto end;
+ }
+
+ /* add end attribute to end */
+ pushBackList(attr, newEmptyAttr(ATTR_END));
+
+ i = sendNgPacket(nga, CODE_READ_REQ, attr);
+
+ /* the list will be filled again by recvNgPacket */
+ clearList(attr, (void(*)(void*))freeAttr);
+
+ if (i >= 0)
+ i = recvNgPacket(nga, CODE_READ_REP, &err, &attr_error, attr, filter_attr);
+
+ if (i == -EINVAL) {
+ ret = ERR_INVARG;
+ goto end;
+ } else if (i < 0) {
+ ret = ( errno == EAGAIN || errno == EWOULDBLOCK ) ? ERR_TIMEOUT : ERR_NET;
+ goto end;
+ }
+
+
+ /* check the switch error code */
+ ret = checkErrorCode(err, attr_error);
+
+
+end:
+ return ret;
}
+int writeRequest (struct ngadmin *nga, List *attr)
+{
+ int i, ret = ERR_OK;
+ unsigned char err;
+ unsigned short attr_error;
+
+
+ if (nga == NULL) {
+ ret = ERR_INVARG;
+ goto end;
+ } else if (nga->current == NULL) {
+ ret = ERR_NOTLOG;
+ goto end;
+ }
+
+
+ if (attr == NULL)
+ attr = createEmptyList();
+
+ /* add password attribute to start */
+ pushFrontList(attr, newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password)));
+
+ /* add end attribute to end */
+ pushBackList(attr, newEmptyAttr(ATTR_END));
+
+ i = sendNgPacket(nga, CODE_WRITE_REQ, attr);
+
+ /* the list will be filled again by recvNgPacket
+ but normally it will be still empty */
+ clearList(attr, (void(*)(void*))freeAttr);
+
+ if (i >= 0)
+ i = recvNgPacket(nga, CODE_WRITE_REP, &err, &attr_error, attr, ATTR_END);
+
+ if (i == -EINVAL) {
+ ret = ERR_INVARG;
+ goto end;
+ } else if (i < 0) {
+ ret = ( errno==EAGAIN || errno==EWOULDBLOCK ) ? ERR_TIMEOUT : ERR_NET ;
+ goto end;
+ }
+
+ /* check the switch error code */
+ ret = checkErrorCode(err, attr_error);
+
+
+end:
+ /* the switch replies to write request by just a header (no attributes), so the list can be destroyed */
+ destroyList(attr, (void(*)(void*))freeAttr);
+
+
+ return ret;
+}
+
-// -----------------------------------------------
-int writeRequest (struct ngadmin *nga, List *attr) {
-
- int i, ret=ERR_OK;
- unsigned char err;
- unsigned short attr_error;
-
-
- if ( nga==NULL ) {
- ret=ERR_INVARG;
- goto end;
- } else if ( nga->current==NULL ) {
- ret=ERR_NOTLOG;
- goto end;
- }
-
-
- if ( attr==NULL ) {
- attr=createEmptyList();
- }
-
- // add password attribute to start
- pushFrontList(attr, newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password)));
-
- // add end attribute to end
- pushBackList(attr, newEmptyAttr(ATTR_END));
-
- i=sendNgPacket(nga, CODE_WRITE_REQ, attr);
-
- // the list will be filled again by recvNgPacket
- // but normally it will be still empty
- clearList(attr, (void(*)(void*))freeAttr);
-
- if ( i<0 || (i=recvNgPacket(nga, CODE_WRITE_REP, &err, &attr_error, attr))<0 ) {
- ret= ( errno==EAGAIN || errno==EWOULDBLOCK ) ? ERR_TIMEOUT : ERR_NET ;
- goto end;
- }
-
- // check error code
- ret=checkErrorCode(err, attr_error);
-
-
- end:
- // the switch replies to write request by just a header (no attributes), so the list can be destroyed
- destroyList(attr, (void(*)(void*))freeAttr);
-
-
- return ret;
-
+void extractSwitchAttributes (struct swi_attr *sa, const List *l)
+{
+ const ListNode *ln;
+ const struct attr *at;
+ int len;
+
+
+ memset(sa, 0, sizeof(struct swi_attr));
+
+ for (ln = l->first; ln != NULL; ln = ln->next) {
+ at = ln->data;
+
+ switch (at->attr) {
+
+ case ATTR_PRODUCT:
+ len = min(at->size, PRODUCT_SIZE);
+ memcpy(sa->product, at->data, len);
+ trim(sa->product, len);
+ break;
+
+ case ATTR_NAME:
+ len = min(at->size, NAME_SIZE);
+ memcpy(sa->name, at->data, len);
+ trim(sa->name, len);
+ break;
+
+ case ATTR_MAC:
+ memcpy(&sa->mac, at->data, ETH_ALEN);
+ break;
+
+ case ATTR_IP:
+ sa->nc.ip = *(struct in_addr*)at->data;
+ break;
+
+ case ATTR_NETMASK:
+ sa->nc.netmask = *(struct in_addr*)at->data;
+ break;
+
+ case ATTR_GATEWAY:
+ sa->nc.gw = *(struct in_addr*)at->data;
+ break;
+
+ case ATTR_DHCP:
+ sa->nc.dhcp = (ntohs(*(unsigned short*)at->data) == 1);
+ break;
+
+ case ATTR_FIRM_VER:
+ len = min(at->size, FIRMWARE_SIZE - 1);
+ memcpy(sa->firmware, at->data, len);
+ sa->firmware[len] = '\0';
+ break;
+
+ case ATTR_PORTS_COUNT:
+ sa->ports = *(unsigned char*)at->data;
+ break;
+
+ case ATTR_END:
+ return;
+ }
+ }
}
#define DEF_NETWORK
-#include <string.h>
-#include <unistd.h>
-//#include <poll.h>
-#include <arpa/inet.h>
-#include <net/if.h>
-#include <netinet/ether.h>
-#include <sys/ioctl.h>
-//#include <sys/time.h>
-
#include "list.h"
#include "lib.h"
-#include "protocol.h"
-
-
-//
int startNetwork (struct ngadmin *nga);
-//
+
int stopNetwork (struct ngadmin *nga);
-//
+
int forceInterface (struct ngadmin *nga);
-//
+
int updateTimeout (struct ngadmin *nga);
-//
+
int sendNgPacket (struct ngadmin *nga, char code, const List *attr);
-//
-int recvNgPacket (struct ngadmin *nga, char code, unsigned char *error, unsigned short *attr_error, List *attr);
-//
-int readRequest (struct ngadmin *nga, List *attr);
+int recvNgPacket (struct ngadmin *nga, char code, unsigned char *error, unsigned short *attr_error, List *attr, unsigned short filter_attr);
+
+
+int readRequest (struct ngadmin *nga, List *attr, unsigned short filter_attr);
+
-//
int writeRequest (struct ngadmin *nga, List *attr);
+void extractSwitchAttributes (struct swi_attr *sa, const List *l);
+
#endif
-#include "lib.h"
-#include "network.h"
-
+#include <errno.h>
+#include <ngadmin.h>
-static const struct timeval default_timeout={.tv_sec=4, .tv_usec=0};
-
-
-
-// ---------------------------------------------
-struct ngadmin* ngadmin_init (const char *iface) {
-
- struct ngadmin *nga;
-
-
- // allocate main structure
- nga=malloc(sizeof(struct ngadmin));
- memset(nga, 0, sizeof(struct ngadmin));
-
- strncpy(nga->iface, iface, IFNAMSIZ-1);
-
- if ( startNetwork(nga)<0 ) {
- free(nga);
- return NULL;
- }
-
- nga->timeout=default_timeout;
- if ( updateTimeout(nga)<0 ) {
- free(nga);
- return NULL;
- }
-
-
- return nga;
-
+#include "lib.h"
+#include "network.h"
+#include "attr.h"
+#include "protocol.h"
+
+
+
+static const struct timeval default_timeout = {.tv_sec = 4, .tv_usec = 0};
+
+
+
+struct ngadmin* ngadmin_init (const char *iface)
+{
+ struct ngadmin *nga;
+
+
+ /* allocate main structure */
+ nga = malloc(sizeof(struct ngadmin));
+ memset(nga, 0, sizeof(struct ngadmin));
+
+ strncpy(nga->iface, iface, IFNAMSIZ - 1);
+
+ if (startNetwork(nga) < 0) {
+ free(nga);
+ return NULL;
+ }
+
+ nga->timeout = default_timeout;
+ if (updateTimeout(nga) < 0) {
+ free(nga);
+ return NULL;
+ }
+
+
+ return nga;
}
-
-// ------------------------------------
-int ngadmin_close (struct ngadmin *nga) {
-
- if ( nga==NULL ) {
- return ERR_INVARG;
- }
-
-
- stopNetwork(nga);
- free(nga->swi_tab);
- free(nga);
-
-
- return ERR_OK;
-
+int ngadmin_close (struct ngadmin *nga)
+{
+ if (nga == NULL)
+ return ERR_INVARG;
+
+ stopNetwork(nga);
+ free(nga->swi_tab);
+ free(nga);
+
+ return ERR_OK;
}
-
-// ---------------------------------------------
-int ngadmin_forceInterface (struct ngadmin *nga) {
-
-
- if ( nga==NULL ) {
- return ERR_INVARG;
- }
-
-
- if ( forceInterface(nga)!=0 ) {
- return ERR_NET;
- } else {
- return ERR_OK;
- }
-
+int ngadmin_forceInterface (struct ngadmin *nga)
+{
+ if (nga == NULL)
+ return ERR_INVARG;
+
+ return forceInterface(nga) == 0 ? ERR_OK : ERR_NET;
}
-
-// --------------------------------------------------------------
-int ngadmin_setKeepBroadcasting (struct ngadmin *nga, bool value) {
-
-
- if ( nga==NULL ) {
- return ERR_INVARG;
- }
-
-
- nga->keepbroad=value;
-
-
- return ERR_OK;
-
+int ngadmin_setKeepBroadcasting (struct ngadmin *nga, bool value)
+{
+ if (nga == NULL)
+ return ERR_INVARG;
+
+ nga->keepbroad = value;
+
+ return ERR_OK;
}
-
-// -------------------------------------------------------------
-int ngadmin_useGlobalBroadcast (struct ngadmin *nga, bool value) {
-
-
- if ( nga==NULL ) {
- return ERR_INVARG;
- }
-
-
- nga->globalbroad=value;
-
-
- return ERR_OK;
-
+int ngadmin_useGlobalBroadcast (struct ngadmin *nga, bool value)
+{
+ if (nga == NULL)
+ return ERR_INVARG;
+
+ nga->globalbroad = value;
+
+ return ERR_OK;
}
-
-// ------------------------------------------------------------
-int ngadmin_setPassword (struct ngadmin *nga, const char *pass) {
-
- if ( nga==NULL ) {
- return ERR_INVARG;
- }
-
-
- strncpy(nga->password, pass, PASSWORD_MAX);
-
-
- return ERR_OK;
-
+int ngadmin_setPassword (struct ngadmin *nga, const char *pass)
+{
+ if (nga == NULL)
+ return ERR_INVARG;
+
+ strncpy(nga->password, pass, PASSWORD_MAX);
+
+ return ERR_OK;
}
-
-// -------------------------------------------------------------------
-int ngadmin_setTimeout (struct ngadmin *nga, const struct timeval *tv) {
-
- int ret=ERR_OK;
-
-
- if ( nga==NULL || tv==NULL ) {
- return ERR_INVARG;
- }
-
-
- nga->timeout=*tv;
- if ( updateTimeout(nga)<0 ) {
- ret=ERR_NET;
- }
-
-
- return ret;
-
+int ngadmin_setTimeout (struct ngadmin *nga, const struct timeval *tv)
+{
+ int ret = ERR_OK;
+
+
+ if (nga == NULL || tv == NULL)
+ return ERR_INVARG;
+
+ nga->timeout = *tv;
+ if (updateTimeout(nga) < 0)
+ ret = ERR_NET;
+
+
+ return ret;
}
-
-// -----------------------------------
-int ngadmin_scan (struct ngadmin *nga) {
-
- int i;
- List *attr, *swiList;
- struct swi_attr *sa;
- /*
- 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
- */
- static const unsigned short hello[]={
- ATTR_PRODUCT,
- ATTR_NAME,
- ATTR_MAC,
- ATTR_IP,
- ATTR_NETMASK,
- ATTR_GATEWAY,
- ATTR_DHCP,
- ATTR_FIRM_VER,
- ATTR_PORTS_COUNT,
- ATTR_END
- };
-
-
- if ( nga==NULL ) {
- return ERR_INVARG;
- }
-
- free(nga->swi_tab);
- nga->swi_tab=NULL;
- nga->swi_count=0;
- nga->current=NULL;
-
-
- // create attributes for an "hello" request
- attr=createEmptyList();
- for (i=0; ; ++i) {
- pushBackList(attr, newEmptyAttr(hello[i]));
- if ( hello[i]==ATTR_END ) break;
- }
-
- // send request to all potential switches
- i=sendNgPacket(nga, CODE_READ_REQ, attr);
- clearList(attr, (void(*)(void*))freeAttr);
- if ( i<0 ) {
- return ERR_NET;
- }
-
-
- // try to receive any packets until timeout
- swiList=createEmptyList();
- // FIXME: end after timeout whatever received packet is good or not
- while ( recvNgPacket(nga, CODE_READ_REP, NULL, NULL, attr)>=0 ) {
- sa=malloc(sizeof(struct swi_attr));
- extractSwitchAttributes(sa, attr);
- clearList(attr, (void(*)(void*))freeAttr);
- pushBackList(swiList, sa);
- }
-
- nga->swi_count=swiList->count;
- nga->swi_tab=convertToArray(swiList, sizeof(struct swi_attr));
- destroyList(swiList, free);
- destroyList(attr, (void(*)(void*))freeAttr);
-
-
- return ERR_OK;
-
+int ngadmin_scan (struct ngadmin *nga)
+{
+ int i;
+ List *attr, *swiList;
+ struct swi_attr *sa;
+ /*
+ 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
+ */
+ static const unsigned short hello[] = {
+ ATTR_PRODUCT,
+ ATTR_NAME,
+ ATTR_MAC,
+ ATTR_IP,
+ ATTR_NETMASK,
+ ATTR_GATEWAY,
+ ATTR_DHCP,
+ ATTR_FIRM_VER,
+ ATTR_PORTS_COUNT,
+ ATTR_END
+ };
+
+
+ if (nga == NULL)
+ return ERR_INVARG;
+
+ free(nga->swi_tab);
+ nga->swi_tab = NULL;
+ nga->swi_count = 0;
+ nga->current = NULL;
+
+
+ /* create attributes for an "hello" request */
+ attr = createEmptyList();
+ for (i = 0; ; i++) {
+ pushBackList(attr, newEmptyAttr(hello[i]));
+ if (hello[i] == ATTR_END)
+ break;
+ }
+
+ /* send request to all potential switches */
+ i = sendNgPacket(nga, CODE_READ_REQ, attr);
+ clearList(attr, (void(*)(void*))freeAttr);
+ if (i == -EINVAL)
+ return ERR_INVARG;
+ else if (i < 0)
+ return ERR_NET;
+
+ /* try to receive any packets until timeout */
+ swiList = createEmptyList();
+ /* FIXME: end after timeout whatever received packet is good or not */
+ while (recvNgPacket(nga, CODE_READ_REP, NULL, NULL, attr, ATTR_END) >= 0) {
+ sa = malloc(sizeof(struct swi_attr));
+ if (sa == NULL)
+ return ERR_MEM;
+ extractSwitchAttributes(sa, attr);
+ clearList(attr, (void(*)(void*))freeAttr);
+ pushBackList(swiList, sa);
+ }
+
+ nga->swi_count = swiList->count;
+ nga->swi_tab = convertToArray(swiList, sizeof(struct swi_attr));
+ destroyList(swiList, free);
+ destroyList(attr, (void(*)(void*))freeAttr);
+
+
+ return ERR_OK;
}
-
-// -----------------------------------------------------------------------
-const struct swi_attr* ngadmin_getSwitchTab (struct ngadmin *nga, int *nb) {
-
-
- if ( nga==NULL || nb==NULL ) {
- return NULL;
- }
-
-
- *nb=nga->swi_count;
-
-
- return nga->swi_tab;
-
+const struct swi_attr* ngadmin_getSwitchTab (struct ngadmin *nga, int *nb)
+{
+ if (nga == NULL || nb == NULL)
+ return NULL;
+
+ *nb = nga->swi_count;
+
+ return nga->swi_tab;
}
-
-// ------------------------------------------------------------------
-const struct swi_attr* ngadmin_getCurrentSwitch (struct ngadmin *nga) {
-
-
- if ( nga==NULL ) {
- return NULL;
- }
-
-
- return nga->current;
-
+const struct swi_attr* ngadmin_getCurrentSwitch (struct ngadmin *nga)
+{
+ if (nga == NULL)
+ return NULL;
+
+ return nga->current;
}
-
-// --------------------------------------------
-int ngadmin_login (struct ngadmin *nga, int id) {
-
- List *attr;
- int ret=ERR_OK;
- struct swi_attr *sa;
-
-
- if ( nga==NULL ) {
- return ERR_INVARG;
- } else if ( id<0 || id>=nga->swi_count ) {
- return ERR_BADID;
- }
-
-
- sa=&nga->swi_tab[id];
- nga->current=sa;
-
- attr=createEmptyList();
- pushBackList(attr, newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password)));
- if ( (ret=readRequest(nga, attr))==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
- } else {
- // login failed
- nga->current=NULL;
- }
-
- destroyList(attr, (void(*)(void*))freeAttr);
-
-
- return ret;
-
+int ngadmin_login (struct ngadmin *nga, int id)
+{
+ List *attr;
+ int ret = ERR_OK;
+ struct swi_attr *sa;
+
+
+ if (nga == NULL)
+ return ERR_INVARG;
+ else if (id < 0 || id >= nga->swi_count)
+ return ERR_BADID;
+
+ sa = &nga->swi_tab[id];
+ nga->current = sa;
+
+ attr = createEmptyList();
+ pushBackList(attr, newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password)));
+ ret = readRequest(nga, attr, ATTR_END);
+ 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 */
+ } else {
+ /* login failed */
+ nga->current = NULL;
+ }
+
+ destroyList(attr, (void(*)(void*))freeAttr);
+
+
+ return ret;
}
-
-// --------------------------------------------------------------------
-int ngadmin_upgradeFirmware (struct ngadmin *nga, const char *filename) {
-
-
- if ( nga==NULL || filename==NULL || *filename==0 ) {
- return ERR_INVARG;
- } 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.
- */
-
- return ERR_NOTIMPL;
-
+int ngadmin_upgradeFirmware (struct ngadmin *nga, const char *filename)
+{
+ if (nga == NULL || filename == NULL || *filename == 0)
+ return ERR_INVARG;
+ 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.
+ */
+
+ return ERR_NOTIMPL;
}
-
-// -------------------------------------------------------------------
-int ngadmin_getPortsStatus (struct ngadmin *nga, unsigned char *ports) {
-
- List *attr;
- ListNode *ln;
- struct attr *at;
- int ret=ERR_OK, i;
- char *p;
-
-
- if ( nga==NULL || ports==NULL ) {
- return ERR_INVARG;
- } else if ( nga->current==NULL ) {
- return ERR_NOTLOG;
- }
-
-
- attr=createEmptyList();
- pushBackList(attr, newEmptyAttr(ATTR_PORT_STATUS));
- if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
- goto end;
- }
-
- for (ln=attr->first; ln!=NULL; ln=ln->next) {
- at=ln->data;
- p=at->data;
- if ( at->attr==ATTR_PORT_STATUS && at->size>=2 && (i=p[0]-1)>=0 && i<nga->current->ports ) {
- ports[i]=p[1];
- }
- }
-
-
- end:
- destroyList(attr, (void(*)(void*))freeAttr);
-
-
- return ret;
-
+int ngadmin_getPortsStatus (struct ngadmin *nga, unsigned char *ports)
+{
+ List *attr;
+ ListNode *ln;
+ struct attr *at;
+ int ret = ERR_OK;
+ struct attr_port_status *ps;
+
+
+ if (nga == NULL || ports == NULL)
+ return ERR_INVARG;
+ else if (nga->current == NULL)
+ return ERR_NOTLOG;
+
+
+ attr = createEmptyList();
+ pushBackList(attr, newEmptyAttr(ATTR_PORT_STATUS));
+ ret = readRequest(nga, attr, ATTR_PORT_STATUS);
+ if (ret != ERR_OK)
+ goto end;
+
+ memset(ports, SPEED_UNK, nga->current->ports);
+
+ for (ln = attr->first; ln != NULL; ln = ln->next) {
+ at = ln->data;
+ ps = at->data;
+ ports[ps->port - 1] = ps->status;
+ }
+
+end:
+ destroyList(attr, (void(*)(void*))freeAttr);
+
+
+ return ret;
}
-
-// --------------------------------------------------------
-int ngadmin_setName (struct ngadmin *nga, const char *name) {
-
- List *attr;
- int ret=ERR_OK;
-
-
- if ( nga==NULL ) {
- return ERR_INVARG;
- } else if ( nga->current==NULL ) {
- return ERR_NOTLOG;
- }
-
-
- attr=createEmptyList();
- pushBackList(attr, name==NULL ? newEmptyAttr(ATTR_NAME) : newAttr(ATTR_NAME, strlen(name), strdup(name)) );
- if ( (ret=writeRequest(nga, attr))!=ERR_OK ) {
- goto end;
- }
-
-
- // successful, also update local name
- if ( name==NULL ) {
- nga->current->name[0]=0;
- } else {
- strncpy(nga->current->name, name, NAME_SIZE);
- }
-
-
- end:
-
- return ret;
-
+int ngadmin_setName (struct ngadmin *nga, const char *name)
+{
+ List *attr;
+ int ret = ERR_OK;
+
+
+ if (nga == NULL)
+ return ERR_INVARG;
+ else if (nga->current == NULL)
+ return ERR_NOTLOG;
+
+
+ attr = createEmptyList();
+ pushBackList(attr, name == NULL ? newEmptyAttr(ATTR_NAME) : newAttr(ATTR_NAME, strlen(name), strdup(name)) );
+ ret = writeRequest(nga, attr);
+ if (ret != ERR_OK)
+ goto end;
+
+ /* successful, also update local name */
+ if (name == NULL)
+ memset(nga->current->name, '\0', NAME_SIZE);
+ else
+ strncpy(nga->current->name, name, NAME_SIZE);
+
+end:
+ return ret;
}
-
-// ------------------------------------------------------------------------
-int ngadmin_getPortsStatistics (struct ngadmin *nga, struct port_stats *ps) {
-
- List *attr;
- ListNode *ln;
- struct attr *at;
- int ret=ERR_OK;
- int port;
-
-
- if ( nga==NULL || ps==NULL ) {
- return ERR_INVARG;
- } else if ( nga->current==NULL ) {
- return ERR_NOTLOG;
- }
-
-
- attr=createEmptyList();
- pushBackList(attr, newEmptyAttr(ATTR_PORT_STATISTICS));
- if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
- goto end;
- }
-
-
- for (ln=attr->first; ln!=NULL; ln=ln->next) {
- at=ln->data;
- if ( at->attr==ATTR_PORT_STATISTICS && at->size>=49 && (port=(int)(*(char*)at->data)-1)>=0 && port<nga->current->ports ) {
- ps[port].recv=be64toh(*(unsigned long long*)(at->data+1+8*0));
- ps[port].sent=be64toh(*(unsigned long long*)(at->data+1+8*1));
- ps[port].crc=be64toh(*(unsigned long long*)(at->data+1+8*5));
- // all offsets between 2 and 4 inclusive are unknown values
- }
- }
-
-
- end:
- destroyList(attr, (void(*)(void*))freeAttr);
-
-
- return ret;
-
+int ngadmin_getPortsStatistics (struct ngadmin *nga, struct port_stats *ps)
+{
+ List *attr;
+ ListNode *ln;
+ struct attr *at;
+ int ret = ERR_OK;
+ struct attr_port_stat *aps;
+
+
+ if (nga == NULL || ps == NULL)
+ return ERR_INVARG;
+ else if (nga->current == NULL)
+ return ERR_NOTLOG;
+
+ attr = createEmptyList();
+ pushBackList(attr, newEmptyAttr(ATTR_PORT_STATISTICS));
+ ret = readRequest(nga, attr, ATTR_PORT_STATISTICS);
+ if (ret != ERR_OK)
+ goto end;
+
+ memset(ps, 0, nga->current->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;
+ }
+
+end:
+ destroyList(attr, (void(*)(void*))freeAttr);
+
+
+ return ret;
}
-
-// ---------------------------------------------------
-int ngadmin_resetPortsStatistics (struct ngadmin *nga) {
-
- List *attr;
-
-
- attr=createEmptyList();
- pushBackList(attr, newByteAttr(ATTR_STATS_RESET, 1));
-
-
- return writeRequest(nga, attr);
-
+int ngadmin_resetPortsStatistics (struct ngadmin *nga)
+{
+ List *attr;
+
+
+ attr = createEmptyList();
+ pushBackList(attr, newByteAttr(ATTR_STATS_RESET, 1));
+
+
+ return writeRequest(nga, attr);
}
-
-// ---------------------------------------------------------------
-int ngadmin_changePassword (struct ngadmin *nga, const char* pass) {
-
- List *attr;
- int ret=ERR_OK;
-
-
- if ( nga==NULL || pass==NULL ) {
- return ERR_INVARG;
- } else if ( nga->current==NULL ) {
- return ERR_NOTLOG;
- }
-
-
- attr=createEmptyList();
- pushBackList(attr, newAttr(ATTR_NEW_PASSWORD, strlen(pass), strdup(pass)));
- if ( (ret=writeRequest(nga, attr))!=ERR_OK ) {
- goto end;
- }
-
-
- // successful, also update local password
- strncpy(nga->password, pass, PASSWORD_MAX);
-
-
- end:
-
- return ret;
-
+int ngadmin_changePassword (struct ngadmin *nga, const char* pass)
+{
+ List *attr;
+ int ret = ERR_OK;
+
+
+ if (nga == NULL || pass == NULL)
+ return ERR_INVARG;
+ else if (nga->current == NULL)
+ return ERR_NOTLOG;
+
+
+ attr = createEmptyList();
+ pushBackList(attr, newAttr(ATTR_NEW_PASSWORD, strlen(pass), strdup(pass)));
+ ret = writeRequest(nga, attr);
+ if (ret != ERR_OK)
+ goto end;
+
+
+ /* successful, also update local password */
+ strncpy(nga->password, pass, PASSWORD_MAX);
+
+end:
+
+ return ret;
}
-
-// ----------------------------------------------------------
-int ngadmin_getStormFilterState (struct ngadmin *nga, int *s) {
-
- List *attr;
- ListNode *ln;
- struct attr *at;
- int ret=ERR_OK;
-
-
- if ( nga==NULL || s==NULL ) {
- return ERR_INVARG;
- } else if ( nga->current==NULL ) {
- return ERR_NOTLOG;
- }
-
-
- attr=createEmptyList();
- pushBackList(attr, newEmptyAttr(ATTR_STORM_ENABLE));
- if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
- goto end;
- }
-
-
- for (ln=attr->first; ln!=NULL; ln=ln->next) {
- at=ln->data;
- if ( at->attr==ATTR_STORM_ENABLE && at->size>=1 ) {
- *s= *(char*)at->data!=0 ;
- break;
- }
- }
-
-
- end:
- destroyList(attr, (void(*)(void*))freeAttr);
-
-
- return ret;
-
+int ngadmin_getStormFilterState (struct ngadmin *nga, int *s)
+{
+ List *attr;
+ struct attr *at;
+ int ret = ERR_OK;
+
+
+ if (nga == NULL || s == NULL)
+ return ERR_INVARG;
+ else if (nga->current == NULL)
+ return ERR_NOTLOG;
+
+
+ attr = createEmptyList();
+ pushBackList(attr, newEmptyAttr(ATTR_STORM_ENABLE));
+ ret = readRequest(nga, attr, ATTR_STORM_ENABLE);
+ if (ret != ERR_OK)
+ goto end;
+
+ *s = 0;
+
+ if (attr->first != NULL) {
+ at = attr->first->data;
+ *s = *(char*)at->data;
+ }
+
+
+end:
+ destroyList(attr, (void(*)(void*))freeAttr);
+
+
+ return ret;
}
-
-// ---------------------------------------------------------
-int ngadmin_setStormFilterState (struct ngadmin *nga, int s) {
-
- List *attr;
-
-
- attr=createEmptyList();
- pushBackList(attr, newByteAttr(ATTR_STORM_ENABLE, s!=0));
-
-
- return writeRequest(nga, attr);
-
+int ngadmin_setStormFilterState (struct ngadmin *nga, int s)
+{
+ List *attr;
+
+
+ attr = createEmptyList();
+ pushBackList(attr, newByteAttr(ATTR_STORM_ENABLE, s != 0));
+
+
+ return writeRequest(nga, attr);
}
-
-// ---------------------------------------------------------------
-int ngadmin_getStormFilterValues (struct ngadmin *nga, int *ports) {
-
- List *attr;
- ListNode *ln;
- struct attr *at;
- int ret=ERR_OK, i;
-
-
- if ( nga==NULL || ports==NULL ) {
- return ERR_INVARG;
- } else if ( nga->current==NULL ) {
- return ERR_NOTLOG;
- }
-
-
- attr=createEmptyList();
- pushBackList(attr, newEmptyAttr(ATTR_STORM_BITRATE));
- if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
- goto end;
- }
-
-
- for (ln=attr->first; ln!=NULL; ln=ln->next) {
- at=ln->data;
- if ( at->attr==ATTR_STORM_BITRATE && at->size>=5 && (i=(int)*(char*)(at->data)-1)>=0 && i<nga->current->ports ) {
- ports[i]=ntohl(*(int*)(1+(char*)at->data));
- }
- }
-
-
- end:
- destroyList(attr, (void(*)(void*))freeAttr);
-
-
- return ret;
-
+int ngadmin_getStormFilterValues (struct ngadmin *nga, int *ports)
+{
+ List *attr;
+ ListNode *ln;
+ struct attr *at;
+ int ret = ERR_OK, port;
+ struct attr_bitrate *sb;
+
+
+ if (nga == NULL || ports == NULL)
+ return ERR_INVARG;
+ else if (nga->current == NULL)
+ return ERR_NOTLOG;
+
+
+ attr = createEmptyList();
+ pushBackList(attr, newEmptyAttr(ATTR_STORM_BITRATE));
+ ret = readRequest(nga, attr, ATTR_STORM_BITRATE);
+ if (ret != ERR_OK)
+ goto end;
+
+ for (port = 0; port < nga->current->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;
+ }
+
+
+end:
+ destroyList(attr, (void(*)(void*))freeAttr);
+
+
+ return ret;
}
-
-// ---------------------------------------------------------------------
-int ngadmin_setStormFilterValues (struct ngadmin *nga, const int *ports) {
-
- List *attr;
- int i;
- char *p;
-
-
- if ( nga==NULL || ports==NULL ) {
- return ERR_INVARG;
- } else if ( nga->current==NULL ) {
- return ERR_NOTLOG;
- }
-
-
- attr=createEmptyList();
-
- for (i=0; i<nga->current->ports; ++i) {
- if ( ports[i]>=0 && ports[i]<=11 ) {
- p=malloc(5);
- *p=i+1;
- *(int*)(p+1)=htonl(ports[i]);
- pushBackList(attr, newAttr(ATTR_STORM_BITRATE, 5, p));
- }
- }
-
-
- return writeRequest(nga, attr);
-
+int ngadmin_setStormFilterValues (struct ngadmin *nga, const int *ports)
+{
+ List *attr;
+ int port;
+ struct attr_bitrate *sb;
+
+
+ if (nga == NULL || ports == NULL)
+ return ERR_INVARG;
+ else if (nga->current == NULL)
+ return ERR_NOTLOG;
+
+
+ attr = createEmptyList();
+
+ for (port = 0; port < nga->current->ports; port++) {
+ if (ports[port] != BITRATE_UNSPEC) {
+ sb = malloc(sizeof(struct attr_bitrate));
+ if (sb == NULL)
+ return ERR_MEM;
+ sb->port = port + 1;
+ sb->bitrate = ports[port];
+ pushBackList(attr, newAttr(ATTR_STORM_BITRATE, sizeof(struct attr_bitrate), sb));
+ }
+ }
+
+ return writeRequest(nga, attr);
}
-
-// -----------------------------------------------------------
-int ngadmin_getBitrateLimits (struct ngadmin *nga, int *ports) {
-
- List *attr;
- ListNode *ln;
- struct attr *at;
- int ret=ERR_OK;
- struct {
- char port;
- int bitrate;
- } __attribute__((packed)) *p;
-
-
- if ( nga==NULL || ports==NULL ) {
- return ERR_INVARG;
- } else if ( nga->current==NULL ) {
- return ERR_NOTLOG;
- }
-
-
- attr=createEmptyList();
- pushBackList(attr, newEmptyAttr(ATTR_BITRATE_INPUT));
- pushBackList(attr, newEmptyAttr(ATTR_BITRATE_OUTPUT));
- if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
- goto end;
- }
-
-
- for (ln=attr->first; ln!=NULL; ln=ln->next) {
- at=ln->data;
- p=at->data;
- if ( at->size<sizeof(*p) || p->port<1 || p->port>nga->current->ports ) continue;
- if ( at->attr==ATTR_BITRATE_INPUT ) {
- ports[(p->port-1)*2+0]=ntohl(p->bitrate);
- } else if ( at->attr==ATTR_BITRATE_OUTPUT ) {
- ports[(p->port-1)*2+1]=ntohl(p->bitrate);
- }
- }
-
-
- end:
- destroyList(attr, (void(*)(void*))freeAttr);
-
-
- return ret;
-
+int ngadmin_getBitrateLimits (struct ngadmin *nga, int *ports)
+{
+ List *attr;
+ ListNode *ln;
+ struct attr *at;
+ int ret = ERR_OK, port;
+ struct attr_bitrate *pb;
+
+
+ if (nga == NULL || ports == NULL)
+ return ERR_INVARG;
+ else if (nga->current == NULL)
+ return ERR_NOTLOG;
+
+
+ attr = createEmptyList();
+ pushBackList(attr, newEmptyAttr(ATTR_BITRATE_INPUT));
+ pushBackList(attr, newEmptyAttr(ATTR_BITRATE_OUTPUT));
+ ret = readRequest(nga, attr, ATTR_END);
+ if (ret != ERR_OK)
+ goto end;
+
+
+ for (port = 0; port < nga->current->ports; port++) {
+ ports[2 * port + 0] = BITRATE_UNSPEC;
+ ports[2 * port + 1] = BITRATE_UNSPEC;
+ }
+
+ for (ln = attr->first; ln != NULL; ln = ln->next) {
+ at = ln->data;
+ pb = at->data;
+ if (at->attr == ATTR_BITRATE_INPUT)
+ ports[(pb->port - 1) * 2 + 0] = pb->bitrate;
+ else if (at->attr == ATTR_BITRATE_OUTPUT)
+ ports[(pb->port - 1) * 2 + 1] = pb->bitrate;
+ }
+
+
+end:
+ destroyList(attr, (void(*)(void*))freeAttr);
+
+ return ret;
}
-
-// -----------------------------------------------------------------
-int ngadmin_setBitrateLimits (struct ngadmin *nga, const int *ports) {
-
- List *attr;
- int i;
- char *p;
-
-
- if ( nga==NULL || ports==NULL ) {
- return ERR_INVARG;
- } else if ( nga->current==NULL ) {
- return ERR_NOTLOG;
- }
-
-
- attr=createEmptyList();
-
- for (i=0; i<nga->current->ports; ++i) {
- if ( ports[2*i+0]>=0 && ports[2*i+0]<=11 ) {
- p=malloc(5);
- *p=i+1;
- *(int*)(p+1)=htonl(ports[2*i+0]);
- pushBackList(attr, newAttr(ATTR_BITRATE_INPUT, 5, p));
- }
- if ( ports[2*i+1]>=0 && ports[2*i+1]<=11 ) {
- p=malloc(5);
- *p=i+1;
- *(int*)(p+1)=htonl(ports[2*i+1]);
- pushBackList(attr, newAttr(ATTR_BITRATE_OUTPUT, 5, p));
- }
- }
-
-
- return writeRequest(nga, attr);
-
+int ngadmin_setBitrateLimits (struct ngadmin *nga, const int *ports)
+{
+ List *attr;
+ int port;
+ struct attr_bitrate *pb;
+
+
+ if (nga == NULL || ports == NULL)
+ return ERR_INVARG;
+ else if (nga->current == NULL)
+ return ERR_NOTLOG;
+
+
+ attr = createEmptyList();
+
+ for (port = 0; port < nga->current->ports; port++) {
+ if (ports[2 * port + 0] >= BITRATE_NOLIMIT && ports[2 * port + 0] <= BITRATE_512M) {
+ pb = malloc(sizeof(struct attr_bitrate));
+ if (pb == NULL)
+ return ERR_MEM;
+ pb->port = port + 1;
+ pb->bitrate = ports[2 * port + 0];
+ pushBackList(attr, newAttr(ATTR_BITRATE_INPUT, sizeof(struct attr_bitrate), pb));
+ }
+ if (ports[2 * port + 1] >= BITRATE_NOLIMIT && ports[2 * port + 1] <= BITRATE_512M) {
+ pb = malloc(sizeof(struct attr_bitrate));
+ if (pb == NULL)
+ return ERR_MEM;
+ pb->port = port + 1;
+ pb->bitrate = ports[2 * port + 1];
+ pushBackList(attr, newAttr(ATTR_BITRATE_OUTPUT, sizeof(struct attr_bitrate), pb));
+ }
+ }
+
+
+ return writeRequest(nga, attr);
}
-
-// -------------------------------------------------
-int ngadmin_getQOSMode (struct ngadmin *nga, int *s) {
-
- List *attr;
- ListNode *ln;
- struct attr *at;
- int ret=ERR_OK;
-
-
- if ( nga==NULL || s==NULL ) {
- return ERR_INVARG;
- } else if ( nga->current==NULL ) {
- return ERR_NOTLOG;
- }
-
-
- attr=createEmptyList();
- pushBackList(attr, newEmptyAttr(ATTR_QOS_TYPE));
- if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
- goto end;
- }
-
-
- for (ln=attr->first; ln!=NULL; ln=ln->next) {
- at=ln->data;
- if ( at->attr==ATTR_QOS_TYPE && at->size>=1 ) {
- *s= *(char*)at->data ;
- break;
- }
- }
-
-
- end:
- destroyList(attr, (void(*)(void*))freeAttr);
-
-
- return ret;
-
+int ngadmin_getQOSMode (struct ngadmin *nga, int *s)
+{
+ List *attr;
+ struct attr *at;
+ int ret = ERR_OK;
+
+
+ if (nga == NULL || s == NULL)
+ return ERR_INVARG;
+ else if (nga->current == NULL)
+ return ERR_NOTLOG;
+
+
+ attr = createEmptyList();
+ pushBackList(attr, newEmptyAttr(ATTR_QOS_TYPE));
+ ret = readRequest(nga, attr, ATTR_QOS_TYPE);
+ if (ret != ERR_OK)
+ goto end;
+
+ *s = 0;
+
+ if (attr->first != NULL) {
+ at = attr->first->data;
+ *s = *(char*)at->data;
+ }
+
+
+end:
+ destroyList(attr, (void(*)(void*))freeAttr);
+
+
+ return ret;
}
-// ------------------------------------------------
-int ngadmin_setQOSMode (struct ngadmin *nga, int s) {
-
- List *attr;
-
-
- if ( s<QOS_PORT || s>QOS_DOT ) {
- return ERR_INVARG;
- }
-
- attr=createEmptyList();
- pushBackList(attr, newByteAttr(ATTR_QOS_TYPE, s));
-
-
- return writeRequest(nga, attr);
-
+int ngadmin_setQOSMode (struct ngadmin *nga, int s)
+{
+ List *attr;
+
+
+ attr = createEmptyList();
+ pushBackList(attr, newByteAttr(ATTR_QOS_TYPE, s));
+
+
+ return writeRequest(nga, attr);
}
-
-// -------------------------------------------------------
-int ngadmin_getQOSValues (struct ngadmin *nga, char *ports) {
-
- List *attr;
- ListNode *ln;
- struct attr *at;
- int ret=ERR_OK;
- char *p;
-
-
- if ( nga==NULL || ports==NULL ) {
- return ERR_INVARG;
- } else if ( nga->current==NULL ) {
- return ERR_NOTLOG;
- }
-
-
- attr=createEmptyList();
- pushBackList(attr, newEmptyAttr(ATTR_QOS_CONFIG));
- if ( (ret=readRequest(nga, attr))<0 ) {
- goto end;
- }
-
- for (ln=attr->first; ln!=NULL; ln=ln->next) {
- at=ln->data;
- p=at->data;
- if ( at->attr==ATTR_QOS_CONFIG && at->size>=2 && --p[0]>=0 && p[0]<nga->current->ports ) {
- ports[(int)p[0]]=p[1];
- }
- }
-
-
- end:
- destroyList(attr, (void(*)(void*))freeAttr);
-
-
- return ret;
-
+int ngadmin_getQOSValues (struct ngadmin *nga, char *ports)
+{
+ List *attr;
+ ListNode *ln;
+ struct attr *at;
+ int ret = ERR_OK, port;
+ struct attr_qos *aq;
+
+
+ if (nga == NULL || ports == NULL)
+ return ERR_INVARG;
+ else if (nga->current == NULL)
+ return ERR_NOTLOG;
+
+
+ attr = createEmptyList();
+ pushBackList(attr, newEmptyAttr(ATTR_QOS_CONFIG));
+ ret = readRequest(nga, attr, ATTR_QOS_CONFIG);
+ if (ret < 0)
+ goto end;
+
+ for (port = 0; port < nga->current->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;
+ }
+
+
+end:
+ destroyList(attr, (void(*)(void*))freeAttr);
+
+
+ return ret;
}
-
-// --------------------------------------------------------------
-int ngadmin_setQOSValues (struct ngadmin *nga, const char *ports) {
-
- List *attr;
- int i;
- char *p;
-
-
- if ( nga==NULL || ports==NULL ) {
- return ERR_INVARG;
- } else if ( nga->current==NULL ) {
- return ERR_NOTLOG;
- }
-
-
- attr=createEmptyList();
-
- for (i=0; i<nga->current->ports; ++i) {
- if ( ports[i]>=PRIO_HIGH && ports[i]<=PRIO_LOW ) {
- p=malloc(2);
- p[0]=i+1;
- p[1]=ports[i];
- pushBackList(attr, newAttr(ATTR_QOS_CONFIG, 2, p));
- }
- }
-
-
- return writeRequest(nga, attr);
-
+int ngadmin_setQOSValues (struct ngadmin *nga, const char *ports)
+{
+ List *attr;
+ int port;
+ struct attr_qos *aq;
+
+
+ if (nga == NULL || ports == NULL)
+ return ERR_INVARG;
+ else if (nga->current == NULL)
+ return ERR_NOTLOG;
+
+
+ attr = createEmptyList();
+
+ for (port = 0; port < nga->current->ports; port++) {
+ if (ports[port] >= PRIO_HIGH && ports[port] <= PRIO_LOW) {
+ aq = malloc(sizeof(struct attr_qos));
+ if (aq == NULL)
+ return ERR_MEM;
+ aq->port = port + 1;
+ aq->prio = ports[port];
+ pushBackList(attr, newAttr(ATTR_QOS_CONFIG, sizeof(struct attr_qos), aq));
+ }
+ }
+
+
+ return writeRequest(nga, attr);
}
-
-// --------------------------------------
-int ngadmin_restart (struct ngadmin *nga) {
-
- List *attr;
-
-
- attr=createEmptyList();
- pushBackList(attr, newByteAttr(ATTR_RESTART, 1));
-
-
- return writeRequest(nga, attr);
-
+int ngadmin_restart (struct ngadmin *nga)
+{
+ List *attr;
+
+
+ attr = createEmptyList();
+ pushBackList(attr, newByteAttr(ATTR_RESTART, 1));
+
+
+ return writeRequest(nga, attr);
}
-
-// ---------------------------------------
-int ngadmin_defaults (struct ngadmin *nga) {
-
- List *attr;
- int ret=ERR_OK;
-
-
- attr=createEmptyList();
- pushBackList(attr, newByteAttr(ATTR_DEFAULTS, 1));
- if ( (ret=writeRequest(nga, attr))!=ERR_OK ) {
- goto end;
- }
-
-
- // successful: delog and clean list
- free(nga->swi_tab);
- nga->swi_tab=NULL;
- nga->swi_count=0;
- nga->current=NULL;
-
-
- end:
-
- return ret;
-
+int ngadmin_defaults (struct ngadmin *nga)
+{
+ List *attr;
+ int ret = ERR_OK;
+
+
+ attr = createEmptyList();
+ pushBackList(attr, newByteAttr(ATTR_DEFAULTS, 1));
+ ret = writeRequest(nga, attr);
+ if (ret != ERR_OK)
+ goto end;
+
+
+ /* successful: delog and clean list */
+ free(nga->swi_tab);
+ nga->swi_tab = NULL;
+ nga->swi_count = 0;
+ nga->current = NULL;
+
+end:
+ return ret;
}
-
-// -----------------------------------------------------
-int ngadmin_getMirror (struct ngadmin *nga, char *ports) {
-
- List *attr;
- ListNode *ln;
- struct attr *at;
- struct swi_attr *sa;
- int ret=ERR_OK, i;
- unsigned char *p;
-
-
- if ( nga==NULL || ports==NULL ) {
- return ERR_INVARG;
- } else if ( (sa=nga->current)==NULL ) {
- return ERR_NOTLOG;
- }
-
-
- attr=createEmptyList();
- pushBackList(attr, newEmptyAttr(ATTR_MIRROR));
- if ( (ret=readRequest(nga, attr))<0 ) {
- goto end;
- }
-
- for (ln=attr->first; ln!=NULL; ln=ln->next) {
- at=ln->data;
- p=at->data;
- if ( at->attr==ATTR_MIRROR && at->size>=3 && p[0]<=nga->current->ports ) {
- ports[0]=p[0];
- for (i=1; i<=sa->ports; ++i) { // FIXME: if ports>8
- ports[i]=(p[2]>>(8-i))&1;
- }
- break;
- }
- }
-
-
- end:
- destroyList(attr, (void(*)(void*))freeAttr);
-
-
- return ret;
-
+int ngadmin_getMirror (struct ngadmin *nga, char *ports)
+{
+ List *attr;
+ struct attr *at;
+ int ret = ERR_OK;
+
+
+ if (nga == NULL || ports == NULL)
+ return ERR_INVARG;
+ else if (nga->current == NULL)
+ return ERR_NOTLOG;
+
+
+ attr = createEmptyList();
+ pushBackList(attr, newEmptyAttr(ATTR_MIRROR));
+ ret = readRequest(nga, attr, ATTR_MIRROR);
+ if (ret < 0)
+ goto end;
+
+ memset(ports, 0, 1 + nga->current->ports);
+
+ if (attr->first != NULL) {
+ at = attr->first->data;
+ memcpy(ports, at->data, 1 + nga->current->ports);
+ }
+
+
+end:
+ destroyList(attr, (void(*)(void*))freeAttr);
+
+
+ return ret;
}
-
-// -----------------------------------------------------------
-int ngadmin_setMirror (struct ngadmin *nga, const char *ports) {
-
- List *attr;
- int i;
- char *p;
- struct swi_attr *sa;
-
-
- if ( nga==NULL ) {
- return ERR_INVARG;
- } else if ( (sa=nga->current)==NULL ) {
- return ERR_NOTLOG;
- }
-
-
- p=malloc(3); // FIXME: if ports>8
- memset(p, 0, 3);
-
- if ( ports!=NULL && ports[0]>0 && ports[0]<=sa->ports ) {
- p[0]=ports[0];
- for (i=1; i<=sa->ports; ++i) {
- if ( i!=p[0] ) {
- p[2]|=(ports[i]&1)<<(8-i);
- }
- }
- }
-
- attr=createEmptyList();
- pushBackList(attr, newAttr(ATTR_MIRROR, 3, p));
-
-
- return writeRequest(nga, attr);
-
+int ngadmin_setMirror (struct ngadmin *nga, const char *ports)
+{
+ List *attr;
+ char *p;
+
+
+ if (nga == NULL)
+ return ERR_INVARG;
+ else if (nga->current == NULL)
+ return ERR_NOTLOG;
+
+
+ p = malloc(1 + nga->current->ports);
+ if (p == NULL)
+ return ERR_MEM;
+
+ if (ports == NULL)
+ memset(p, 0, 1 + nga->current->ports);
+ else
+ memcpy(p, ports, 1 + nga->current->ports);
+
+ attr = createEmptyList();
+ pushBackList(attr, newAttr(ATTR_MIRROR, 1 + nga->current->ports, p));
+
+
+ return writeRequest(nga, attr);
}
-
-// ----------------------------------------------------------------
-int ngadmin_getIGMPConf (struct ngadmin *nga, struct igmp_conf *ic) {
-
- List *attr;
- ListNode *ln;
- struct attr *at;
- struct swi_attr *sa;
- int ret=ERR_OK;
- unsigned char *p;
- unsigned short *s;
-
-
- if ( nga==NULL || ic==NULL ) {
- return ERR_INVARG;
- } else if ( (sa=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=createEmptyList();
- memset(ic, 0, sizeof(struct igmp_conf));
-
-
- pushBackList(attr, newEmptyAttr(ATTR_IGMP_ENABLE_VLAN));
- if ( (ret=readRequest(nga, attr))<0 ) {
- goto end;
- }
-
- for (ln=attr->first; ln!=NULL; ln=ln->next) {
- at=ln->data;
- s=at->data;
- if ( at->attr==ATTR_IGMP_ENABLE_VLAN && at->size>=4 ) {
- ic->enable= ntohs(s[0])!=0 ;
- ic->vlan=htons(s[1]);
- break;
- }
- }
-
- clearList(attr, (void(*)(void*))freeAttr);
-
-
- pushBackList(attr, newEmptyAttr(ATTR_IGMP_BLOCK_UNK));
- if ( (ret=readRequest(nga, attr))<0 ) {
- goto end;
- }
-
- for (ln=attr->first; ln!=NULL; ln=ln->next) {
- at=ln->data;
- p=at->data;
- if ( at->attr==ATTR_IGMP_BLOCK_UNK && at->size>=1 ) {
- ic->block= p[0]!=0 ;
- break;
- }
- }
-
- clearList(attr, (void(*)(void*))freeAttr);
-
-
- pushBackList(attr, newEmptyAttr(ATTR_IGMP_VALID_V3));
- if ( (ret=readRequest(nga, attr))<0 ) {
- goto end;
- }
-
- for (ln=attr->first; ln!=NULL; ln=ln->next) {
- at=ln->data;
- p=at->data;
- if ( at->attr==ATTR_IGMP_VALID_V3 && at->size>=1 ) {
- ic->validate= p[0]!=0 ;
- break;
- }
- }
-
-
-
- end:
- destroyList(attr, (void(*)(void*))freeAttr);
-
-
- return ret;
-
+int ngadmin_getIGMPConf (struct ngadmin *nga, struct igmp_conf *ic)
+{
+ List *attr;
+ struct attr *at;
+ int ret = ERR_OK;
+ struct attr_igmp_vlan *aiv;
+
+
+ if (nga == NULL || ic == NULL)
+ return ERR_INVARG;
+ 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 = createEmptyList();
+ memset(ic, 0, sizeof(struct igmp_conf));
+
+
+ pushBackList(attr, newEmptyAttr(ATTR_IGMP_ENABLE_VLAN));
+ ret = readRequest(nga, attr, ATTR_IGMP_ENABLE_VLAN);
+ if (ret < 0)
+ goto end;
+
+ if (attr->first != NULL) {
+ at = attr->first->data;
+ aiv = at->data;
+ ic->enable = aiv->enable;
+ ic->vlan = aiv->vlan;
+ }
+
+ clearList(attr, (void(*)(void*))freeAttr);
+
+
+ pushBackList(attr, newEmptyAttr(ATTR_IGMP_BLOCK_UNK));
+ ret = readRequest(nga, attr, ATTR_IGMP_BLOCK_UNK);
+ if (ret < 0)
+ goto end;
+
+ if (attr->first != NULL) {
+ at = attr->first->data;
+ ic->block = *(char*)at->data;
+ }
+
+ clearList(attr, (void(*)(void*))freeAttr);
+
+
+ pushBackList(attr, newEmptyAttr(ATTR_IGMP_VALID_V3));
+ ret = readRequest(nga, attr, ATTR_IGMP_VALID_V3);
+ if (ret < 0)
+ goto end;
+
+ if (attr->first != NULL) {
+ at = attr->first->data;
+ ic->validate = *(char*)at->data;
+ }
+
+
+end:
+ destroyList(attr, (void(*)(void*))freeAttr);
+
+
+ return ret;
}
-
-// ----------------------------------------------------------------------
-int ngadmin_setIGMPConf (struct ngadmin *nga, const struct igmp_conf *ic) {
-
- List *attr;
- short *s;
- struct swi_attr *sa;
-
-
- if ( nga==NULL || ic==NULL ) {
- return ERR_INVARG;
- } else if ( (sa=nga->current)==NULL ) {
- return ERR_NOTLOG;
- }
-
-
- s=malloc(2*sizeof(short));
- s[0]=htons(ic->enable!=false);
- s[1]=htons(ic->vlan&0x0FFF);
-
- attr=createEmptyList();
- pushBackList(attr, newAttr(ATTR_IGMP_ENABLE_VLAN, 2*sizeof(short), s));
- pushBackList(attr, newByteAttr(ATTR_IGMP_BLOCK_UNK, ic->block!=false ));
- pushBackList(attr, newByteAttr(ATTR_IGMP_VALID_V3, ic->validate!=false ));
-
-
- return writeRequest(nga, attr);
-
+int ngadmin_setIGMPConf (struct ngadmin *nga, const struct igmp_conf *ic)
+{
+ List *attr;
+ struct attr_igmp_vlan *aiv;
+
+
+ if (nga == NULL || ic == NULL)
+ return ERR_INVARG;
+ else if (nga->current == NULL)
+ return ERR_NOTLOG;
+
+
+ aiv = malloc(sizeof(struct attr_igmp_vlan));
+ if (aiv == NULL)
+ return ERR_MEM;
+ aiv->enable = ic->enable;
+ aiv->vlan = ic->vlan;
+
+
+ attr = createEmptyList();
+ pushBackList(attr, newAttr(ATTR_IGMP_ENABLE_VLAN, sizeof(struct attr_igmp_vlan), aiv));
+ pushBackList(attr, newByteAttr(ATTR_IGMP_BLOCK_UNK, ic->block != false));
+ pushBackList(attr, newByteAttr(ATTR_IGMP_VALID_V3, ic->validate != false));
+
+
+ return writeRequest(nga, attr);
}
-
-// ----------------------------------------------------------------------
-int ngadmin_cabletest (struct ngadmin *nga, struct cabletest *ct, int nb) {
-
- List *attr;
- ListNode *ln;
- struct attr *at;
- int i, ret=ERR_OK;
- struct swi_attr *sa;
- char *p;
-
-
- if ( nga==NULL || ct==NULL ) {
- return ERR_INVARG;
- } else if ( (sa=nga->current)==NULL ) {
- return ERR_NOTLOG;
- }
-
-
- attr=createEmptyList();
-
- for (i=0; i<nb; ++i) {
- if ( ct[i].port>=1 && ct[i].port<=sa->ports ) {
-
- p=malloc(2);
- p[0]=ct[i].port;
- p[1]=1;
- pushBackList(attr, newAttr(ATTR_CABLETEST_DO, 2, p));
-
- ret=writeRequest(nga, attr);
- attr=NULL;
- if ( ret<0 ) goto end;
-
- // the list is destroyed by writeRequest, so we need to recreate it
- attr=createEmptyList();
- pushBackList(attr, newByteAttr(ATTR_CABLETEST_RESULT, ct[i].port));
-
- if ( (ret=readRequest(nga, attr))<0 ) goto end;
-
- for (ln=attr->first; ln!=NULL; ln=ln->next) {
- at=ln->data;
- p=at->data;
- if ( at->attr==ATTR_CABLETEST_RESULT && at->size>=9 && p[0]==ct[i].port ) {
- ct[i].v1=ntohl(*(int*)&p[1]);
- ct[i].v2=ntohl(*(int*)&p[5]);
- break;
- }
- }
-
- // just empty the list, it will be used at next iteration
- clearList(attr, (void(*)(void*))freeAttr);
-
- }
- }
-
-
- end:
- destroyList(attr, (void(*)(void*))freeAttr);
-
-
- return ret;
-
+int ngadmin_cabletest (struct ngadmin *nga, struct cabletest *ct, int nb)
+{
+ List *attr;
+ ListNode *ln;
+ struct attr *at;
+ int ret = ERR_OK, i;
+ struct attr_cabletest_do *acd;
+ struct attr_cabletest_result *acr;
+
+
+ if (nga == NULL || ct == NULL)
+ return ERR_INVARG;
+ else if (nga->current == NULL)
+ return ERR_NOTLOG;
+
+
+ attr = createEmptyList();
+
+ for (i = 0; i < nb; i++) {
+
+ acd = malloc(sizeof(struct attr_cabletest_do));
+ if (acd == NULL)
+ return ERR_MEM;
+ acd->port = ct[i].port;
+ acd->action = 1;
+ pushBackList(attr, newAttr(ATTR_CABLETEST_DO, sizeof(struct attr_cabletest_do), acd));
+
+ ret = writeRequest(nga, attr);
+ attr = NULL;
+ if (ret < 0)
+ goto end;
+
+ /* the list is destroyed by writeRequest, so we need to recreate it */
+ attr = createEmptyList();
+ pushBackList(attr, newByteAttr(ATTR_CABLETEST_RESULT, ct[i].port));
+ ret = readRequest(nga, attr, ATTR_CABLETEST_RESULT);
+ if (ret < 0)
+ goto end;
+
+ for (ln = attr->first; ln != NULL; ln = ln->next) {
+ at = ln->data;
+ acr = at->data;
+ if (at->size == sizeof(struct attr_cabletest_result) && acr->port == ct[i].port) {
+ ct[i].v1 = acr->v1;
+ ct[i].v2 = acr->v2;
+ break;
+ }
+ }
+
+ /* just empty the list, it will be used at next iteration */
+ clearList(attr, (void(*)(void*))freeAttr);
+ }
+
+
+end:
+ destroyList(attr, (void(*)(void*))freeAttr);
+
+
+ return ret;
}
-
-// --------------------------------------------------------------------
-int ngadmin_setNetConf (struct ngadmin *nga, const struct net_conf *nc) {
-
- List *attr;
- struct swi_attr *sa;
- int ret=ERR_OK;
-
-
- if ( nga==NULL || nc==NULL ) {
- return ERR_INVARG;
- } else if ( (sa=nga->current)==NULL ) {
- return ERR_NOTLOG;
- }
-
-
- attr=createEmptyList();
-
- if ( nc->dhcp ) {
- pushBackList(attr, newByteAttr(ATTR_DHCP, 1));
- } else {
- pushBackList(attr, newByteAttr(ATTR_DHCP, 0));
- // only add non-null values
- if ( nc->ip.s_addr!=0 ) pushBackList(attr, newAddrAttr(ATTR_IP, nc->ip));
- if ( nc->netmask.s_addr!=0 ) pushBackList(attr, newAddrAttr(ATTR_NETMASK, nc->netmask));
- if ( nc->gw.s_addr!=0 ) pushBackList(attr, newAddrAttr(ATTR_GATEWAY, nc->gw));
- }
-
- if ( (ret=writeRequest(nga, attr))!=ERR_OK ) {
- goto end;
- }
-
-
- // update local values
- sa->nc.dhcp=nc->dhcp;
- if ( !nc->dhcp ) {
- if ( nc->ip.s_addr!=0 ) sa->nc.ip=nc->ip;
- if ( nc->netmask.s_addr!=0 ) sa->nc.netmask=nc->netmask;
- if ( nc->gw.s_addr!=0 ) sa->nc.gw=nc->gw;
- }
-
-
- end:
-
- return ret;
-
+int ngadmin_setNetConf (struct ngadmin *nga, const struct net_conf *nc)
+{
+ List *attr;
+ int ret = ERR_OK;
+ struct swi_attr *sa;
+
+
+ if (nga == NULL || nc == NULL)
+ return ERR_INVARG;
+
+ sa = nga->current;
+ if (sa == NULL)
+ return ERR_NOTLOG;
+
+
+ attr = createEmptyList();
+
+ if (nc->dhcp) {
+ pushBackList(attr, newShortAttr(ATTR_DHCP, 1));
+ } else {
+ pushBackList(attr, newShortAttr(ATTR_DHCP, 0));
+ /* only add non-null values */
+ if (nc->ip.s_addr != 0)
+ pushBackList(attr, newAddrAttr(ATTR_IP, nc->ip));
+ if (nc->netmask.s_addr != 0)
+ pushBackList(attr, newAddrAttr(ATTR_NETMASK, nc->netmask));
+ if (nc->gw.s_addr != 0)
+ pushBackList(attr, newAddrAttr(ATTR_GATEWAY, nc->gw));
+ }
+
+ ret = writeRequest(nga, attr);
+ if (ret != ERR_OK)
+ goto end;
+
+
+ /* update local values */
+ sa->nc.dhcp = nc->dhcp;
+ if (!nc->dhcp) {
+ if (nc->ip.s_addr !=0)
+ sa->nc.ip = nc->ip;
+ if (nc->netmask.s_addr != 0)
+ sa->nc.netmask = nc->netmask;
+ if (nc->gw.s_addr != 0)
+ sa->nc.gw = nc->gw;
+ }
+
+
+end:
+
+ return ret;
}
-
-// --------------------------------------------------
-int ngadmin_getVLANType (struct ngadmin *nga, int *t) {
-
- List *attr;
- ListNode *ln;
- struct attr *at;
- int ret=ERR_OK;
-
-
- if ( nga==NULL || t==NULL ) {
- return ERR_INVARG;
- } else if ( nga->current==NULL ) {
- return ERR_NOTLOG;
- }
-
-
- attr=createEmptyList();
- pushBackList(attr, newEmptyAttr(ATTR_VLAN_TYPE));
- if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
- goto end;
- }
-
-
- for (ln=attr->first; ln!=NULL; ln=ln->next) {
- at=ln->data;
- if ( at->attr==ATTR_VLAN_TYPE && at->size>=1 ) {
- *t= (int)*(char*)at->data ;
- break;
- }
- }
-
-
- end:
- destroyList(attr, (void(*)(void*))freeAttr);
-
-
- return ret;
-
+int ngadmin_getVLANType (struct ngadmin *nga, int *t)
+{
+ List *attr;
+ struct attr *at;
+ int ret = ERR_OK;
+
+
+ if (nga == NULL || t == NULL)
+ return ERR_INVARG;
+ else if (nga->current == NULL)
+ return ERR_NOTLOG;
+
+
+ attr = createEmptyList();
+ pushBackList(attr, newEmptyAttr(ATTR_VLAN_TYPE));
+ ret=readRequest(nga, attr, ATTR_VLAN_TYPE);
+ if (ret != ERR_OK)
+ goto end;
+
+ *t = VLAN_DISABLED;
+
+ if (attr->first != NULL) {
+ at = attr->first->data;
+ *t =(int)*(char*)at->data;
+ }
+
+
+end:
+ destroyList(attr, (void(*)(void*))freeAttr);
+
+
+ return ret;
}
-
-// -------------------------------------------------
-int ngadmin_setVLANType (struct ngadmin *nga, int t) {
-
- List *attr;
- struct swi_attr *sa;
-
-
- if ( nga==NULL || t<1 || t>4 ) {
- return ERR_INVARG;
- } else if ( (sa=nga->current)==NULL ) {
- return ERR_NOTLOG;
- }
-
-
- attr=createEmptyList();
- pushBackList(attr, newByteAttr(ATTR_VLAN_TYPE, t));
-
-
- return writeRequest(nga, attr);
-
+int ngadmin_setVLANType (struct ngadmin *nga, int t)
+{
+ List *attr;
+
+
+ if (nga == NULL || t < 1 || t > 4)
+ return ERR_INVARG;
+ else if (nga->current == NULL)
+ return ERR_NOTLOG;
+
+
+ attr = createEmptyList();
+ pushBackList(attr, newByteAttr(ATTR_VLAN_TYPE, t));
+
+
+ return writeRequest(nga, attr);
}
-
-// ------------------------------------------------------------------------------------------------------
-int ngadmin_getVLANDotAllConf (struct ngadmin *nga, unsigned short *vlans, unsigned char *ports, int *nb) {
-
- List *attr;
- ListNode *ln;
- struct attr *at;
- struct swi_attr *sa;
- int ret=ERR_OK, total, i;
- char *p=NULL;
-
-
- if ( nga==NULL || vlans==NULL || ports==NULL || nb==NULL || *nb<=0 ) {
- return ERR_INVARG;
- } else if ( (sa=nga->current)==NULL ) {
- return ERR_NOTLOG;
- }
-
-
- total=*nb;
- *nb=0;
-
- attr=createEmptyList();
- pushBackList(attr, newEmptyAttr(ATTR_VLAN_DOT_CONF));
- if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
- goto end;
- }
-
-
- for (ln=attr->first; ln!=NULL; ln=ln->next) {
- at=ln->data;
- p=at->data;
- if ( at->attr==ATTR_VLAN_DOT_CONF && at->size>=4 ) {
- for (i=0; i<sa->ports; ++i) {
- if ( (p[3]>>(7-i))&1 ) ports[i]=VLAN_TAGGED; // tagged
- else if ( (p[2]>>(7-i))&1 ) ports[i]=VLAN_UNTAGGED; // untagged
- else ports[i]=VLAN_NO;
- }
- *vlans++=ntohs(*(unsigned short*)p);
- ports+=sa->ports;
- if ( ++*nb>total ) break; // no more room
- }
- }
-
-
- end:
- destroyList(attr, (void(*)(void*))freeAttr);
-
-
- return ret;
-
+int ngadmin_getVLANDotAllConf (struct ngadmin *nga, unsigned short *vlans, unsigned char *ports, int *nb)
+{
+ List *attr;
+ ListNode *ln;
+ struct attr *at;
+ int ret = ERR_OK, total;
+ struct attr_vlan_dot *avd;
+
+
+ if (nga == NULL || vlans == NULL || ports== NULL || nb == NULL || *nb <= 0)
+ return ERR_INVARG;
+ else if (nga->current == NULL)
+ return ERR_NOTLOG;
+
+
+ total = *nb;
+ *nb = 0;
+
+ attr = createEmptyList();
+ pushBackList(attr, newEmptyAttr(ATTR_VLAN_DOT_CONF));
+ ret = readRequest(nga, attr, ATTR_VLAN_DOT_CONF);
+ if (ret != ERR_OK)
+ goto end;
+
+ memset(vlans, 0, total * sizeof(unsigned short));
+ memset(ports, 0, total * nga->current->ports);
+
+ for (ln = attr->first; ln != NULL; ln = ln->next) {
+ at = ln->data;
+ avd = at->data;
+
+ *vlans = avd->vlan;
+ memcpy(ports, avd->ports, nga->current->ports);
+
+ vlans++;
+ ports += nga->current->ports;
+ (*nb)++;
+
+ if (*nb > total)
+ break; /* no more room */
+ }
+
+
+end:
+ destroyList(attr, (void(*)(void*))freeAttr);
+
+
+ return ret;
}
-
-// ----------------------------------------------------------------------------------------
-int ngadmin_getVLANDotConf (struct ngadmin *nga, unsigned short vlan, unsigned char *ports) {
-
- List *attr;
- ListNode *ln;
- struct attr *at;
- struct swi_attr *sa;
- int ret=ERR_OK, i;
- char *p=NULL;
-
-
- if ( nga==NULL || vlan<1 || vlan>VLAN_MAX || ports==NULL ) {
- return ERR_INVARG;
- } else if ( (sa=nga->current)==NULL ) {
- return ERR_NOTLOG;
- }
-
-
- attr=createEmptyList();
- pushBackList(attr, newShortAttr(ATTR_VLAN_DOT_CONF, vlan));
- if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
- goto end;
- }
-
-
- for (ln=attr->first; ln!=NULL; ln=ln->next) {
- at=ln->data;
- p=at->data;
- if ( at->attr==ATTR_VLAN_DOT_CONF && at->size>=4 ) {
- for (i=0; i<sa->ports; ++i) {
- if ( (p[3]>>(7-i))&1 ) ports[i]=VLAN_TAGGED; // tagged
- else if ( (p[2]>>(7-i))&1 ) ports[i]=VLAN_UNTAGGED; // untagged
- else ports[i]=VLAN_NO;
- }
- break;
- }
- }
-
-
- end:
- destroyList(attr, (void(*)(void*))freeAttr);
-
-
- return ret;
-
+int ngadmin_getVLANDotConf (struct ngadmin *nga, unsigned short vlan, unsigned char *ports)
+{
+ List *attr;
+ ListNode *ln;
+ struct attr *at;
+ int ret = ERR_OK;
+ struct attr_vlan_dot *avd;
+
+
+ if (nga == NULL || vlan < 1 || vlan > VLAN_MAX || ports == NULL)
+ return ERR_INVARG;
+ else if (nga->current == NULL)
+ return ERR_NOTLOG;
+
+
+ attr = createEmptyList();
+ pushBackList(attr, newShortAttr(ATTR_VLAN_DOT_CONF, vlan));
+ ret = readRequest(nga, attr, ATTR_END);
+ if (ret != ERR_OK)
+ goto end;
+
+ memset(ports, 0, nga->current->ports);
+
+ for (ln = attr->first; ln != NULL; ln = ln->next) {
+ at = ln->data;
+ avd = at->data;
+ if (avd->vlan == vlan) {
+ memcpy(ports, avd->ports, nga->current->ports);
+ break;
+ }
+ }
+
+
+end:
+ destroyList(attr, (void(*)(void*))freeAttr);
+
+
+ return ret;
}
-
-// ----------------------------------------------------------------------------------------------
-int ngadmin_setVLANDotConf (struct ngadmin *nga, unsigned short vlan, const unsigned char *ports) {
-
- List *attr=NULL;
- ListNode *ln;
- struct attr *at;
- struct swi_attr *sa;
- char *p, fl;
- int ret=ERR_OK, i;
-
-
- if ( nga==NULL || vlan<1 || vlan>VLAN_MAX || ports==NULL ) {
- return ERR_INVARG;
- } else if ( (sa=nga->current)==NULL ) {
- return ERR_NOTLOG;
- }
-
-
- // if nothing is to be changed, do nothing
- for (i=0; i<sa->ports && ports[i]==VLAN_UNSPEC; ++i);
- if ( i==sa->ports ) goto end;
-
-
- attr=createEmptyList();
-
- p=malloc(4);
- *(unsigned short*)p=htons(vlan);
- *(unsigned short*)&p[2]=0;
-
- // if all is to be changed, we do not need to read old config
- if ( memchr(ports, VLAN_UNSPEC, sa->ports)!=NULL ) {
-
- pushBackList(attr, newShortAttr(ATTR_VLAN_DOT_CONF, vlan));
- if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
- goto end;
- }
-
- for (ln=attr->first; ln!=NULL; ln=ln->next) {
- at=ln->data;
- if ( at->attr==ATTR_VLAN_DOT_CONF && at->size>=4 ) {
- *(unsigned short*)&p[2]=*(unsigned short*)(at->data+2);
- break;
- }
- }
-
- clearList(attr, (void(*)(void*))freeAttr);
-
- }
-
-
- // apply changes
- for (i=0; i<sa->ports; ++i) {
- fl=(1<<(7-i));
- switch ( ports[i] ) {
- case VLAN_NO:
- p[2]&=~fl;
- p[3]&=~fl;
- break;
- case VLAN_UNTAGGED:
- p[2]|=fl;
- p[3]&=~fl;
- break;
- case VLAN_TAGGED:
- p[2]|=fl;
- p[3]|=fl;
- }
- }
-
-
- pushBackList(attr, newAttr(ATTR_VLAN_DOT_CONF, 4, p));
- ret=writeRequest(nga, attr);
- attr=NULL;
-
-
- end:
- destroyList(attr, (void(*)(void*))freeAttr);
-
-
- return ret;
-
-
+int ngadmin_setVLANDotConf (struct ngadmin *nga, unsigned short vlan, const unsigned char *ports)
+{
+ List *attr = NULL;
+ struct attr *at;
+ struct swi_attr *sa;
+ struct attr_vlan_dot *avd;
+ int ret = ERR_OK, port;
+
+
+ if (nga == NULL || vlan < 1 || vlan > VLAN_MAX || ports == NULL)
+ return ERR_INVARG;
+
+ sa = nga->current;
+ if (sa == NULL)
+ return ERR_NOTLOG;
+
+
+ /* if nothing is to be changed, do nothing */
+ for (port = 0; port < sa->ports && ports[port] == VLAN_UNSPEC; port++);
+ if (port == sa->ports )
+ goto end;
+
+
+ attr = createEmptyList();
+ avd = malloc(sizeof(struct attr_vlan_dot) + sa->ports);
+ if (avd == NULL)
+ return ERR_MEM;
+
+ avd->vlan = vlan;
+
+ /* if all is to be changed, we do not need to read old config */
+ if (memchr(ports, VLAN_UNSPEC, sa->ports) != NULL) {
+
+ pushBackList(attr, newShortAttr(ATTR_VLAN_DOT_CONF, vlan));
+ ret = readRequest(nga, attr, ATTR_VLAN_DOT_CONF);
+ if (ret != ERR_OK)
+ goto end;
+
+ if (attr->first != NULL) {
+ at = attr->first->data;
+ memcpy(avd, at->data, sizeof(struct attr_vlan_dot) + sa->ports);
+ }
+
+ clearList(attr, (void(*)(void*))freeAttr);
+ }
+
+
+ /* apply changes */
+ for (port = 0; port < sa->ports; port++) {
+ if (ports[port] != VLAN_UNSPEC)
+ avd->ports[port] = ports[port];
+ }
+
+
+ pushBackList(attr, newAttr(ATTR_VLAN_DOT_CONF, sizeof(struct attr_vlan_dot) + sa->ports, avd));
+ ret = writeRequest(nga, attr);
+ attr = NULL;
+
+
+end:
+ destroyList(attr, (void(*)(void*))freeAttr);
+
+
+ return ret;
}
-
-// ---------------------------------------------------------------
-int ngadmin_VLANDestroy (struct ngadmin *nga, unsigned short vlan) {
-
- List *attr;
- struct swi_attr *sa;
-
-
- if ( nga==NULL || vlan<1 || vlan>VLAN_MAX ) {
- return ERR_INVARG;
- } else if ( (sa=nga->current)==NULL ) {
- return ERR_NOTLOG;
- }
-
-
- attr=createEmptyList();
- pushBackList(attr, newShortAttr(ATTR_VLAN_DESTROY, vlan));
-
-
- return writeRequest(nga, attr);
-
+int ngadmin_VLANDestroy (struct ngadmin *nga, unsigned short vlan)
+{
+ List *attr;
+
+
+ if (nga == NULL || vlan < 1 || vlan > VLAN_MAX)
+ return ERR_INVARG;
+ else if (nga->current == NULL)
+ return ERR_NOTLOG;
+
+
+ attr = createEmptyList();
+ pushBackList(attr, newShortAttr(ATTR_VLAN_DESTROY, vlan));
+
+
+ return writeRequest(nga, attr);
}
-
-// ----------------------------------------------------------------
-int ngadmin_getAllPVID (struct ngadmin *nga, unsigned short *ports) {
-
- List *attr;
- ListNode *ln;
- struct attr *at;
- struct swi_attr *sa;
- int ret=ERR_OK;
- char *p;
-
-
- if ( nga==NULL || ports==NULL ) {
- return ERR_INVARG;
- } else if ( (sa=nga->current)==NULL ) {
- return ERR_NOTLOG;
- }
-
-
- attr=createEmptyList();
- pushBackList(attr, newEmptyAttr(ATTR_VLAN_PVID));
- if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
- goto end;
- }
-
-
- for (ln=attr->first; ln!=NULL; ln=ln->next) {
- at=ln->data;
- p=at->data;
- if ( at->attr==ATTR_VLAN_PVID && at->size>=3 && p[0]>=1 && p[0]<=sa->ports ) {
- ports[p[0]-1]=htons(*(unsigned short*)&p[1]);
- }
- }
-
-
- end:
- destroyList(attr, (void(*)(void*))freeAttr);
-
-
- return ret;
-
+int ngadmin_getAllPVID (struct ngadmin *nga, unsigned short *ports)
+{
+ List *attr;
+ ListNode *ln;
+ struct attr *at;
+ int ret = ERR_OK;
+ struct attr_pvid *ap;
+
+
+ if (nga == NULL || ports == NULL)
+ return ERR_INVARG;
+ else if (nga->current == NULL)
+ return ERR_NOTLOG;
+
+
+ attr = createEmptyList();
+ pushBackList(attr, newEmptyAttr(ATTR_VLAN_PVID));
+ ret = readRequest(nga, attr, ATTR_VLAN_PVID);
+ if (ret != ERR_OK)
+ goto end;
+
+ memset(ports, 0, nga->current->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;
+ }
+
+
+end:
+ destroyList(attr, (void(*)(void*))freeAttr);
+
+
+ return ret;
}
-
-// -------------------------------------------------------------------------------
-int ngadmin_setPVID (struct ngadmin *nga, unsigned char port, unsigned short vlan) {
-
- List *attr;
- struct swi_attr *sa;
- char *p;
-
-
- if ( nga==NULL || port<1 || vlan<1 || vlan>VLAN_MAX ) {
- return ERR_INVARG;
- } else if ( (sa=nga->current)==NULL ) {
- return ERR_NOTLOG;
- } else if ( port>sa->ports ) {
- return ERR_INVARG;
- }
-
-
- attr=createEmptyList();
- p=malloc(3);
- p[0]=port;
- *(unsigned short*)&p[1]=htons(vlan);
-
- pushBackList(attr, newAttr(ATTR_VLAN_PVID, 3, p));
-
-
- return writeRequest(nga, attr);
-
+int ngadmin_setPVID (struct ngadmin *nga, unsigned char port, unsigned short vlan)
+{
+ List *attr;
+ struct attr_pvid *ap;
+
+
+ if (nga == NULL || port < 1 || vlan < 1 || vlan > VLAN_MAX)
+ return ERR_INVARG;
+ else if (nga->current == NULL)
+ return ERR_NOTLOG;
+ else if (port > nga->current->ports)
+ return ERR_INVARG;
+
+
+ attr = createEmptyList();
+ ap = malloc(sizeof(struct attr_pvid));
+ if (ap == NULL)
+ return ERR_MEM;
+ ap->port = port;
+ ap->vlan = vlan;
+
+ pushBackList(attr, newAttr(ATTR_VLAN_PVID, sizeof(struct attr_pvid), ap));
+
+
+ return writeRequest(nga, attr);
}
-#include "protocol.h"
-
-
-
-
-// ----------------------------
-int trim (char *txt, int start) {
-
- char *p, c;
-
-
- if ( txt==NULL ) {
- return 0;
- }
-
- //for (p=txt; *p!=0; p++);
- p=txt+start;
- for (p--; p>=txt && ( (c=*p)==' ' || c=='\n' ); *p--=0);
-
-
- return p-txt+1;
-
-}
-
-
-
-// -------------------
-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) {
-
-
- 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 initNgPacket (struct ng_packet *np) {
-
- np->ah=(struct attr_header*)np->nh->data;
-
-}
-
-
-
-// --------------------------------------------------------------------------------------------
-void addPacketAttr (struct ng_packet *np, unsigned short attr, unsigned short size, void* data) {
-
- struct attr_header *ah=np->ah;
-
-
- if ( (int)(getPacketTotalSize(np)+sizeof(struct attr_header)+size)>(np->maxlen) ) {
- return;
- }
-
- ah->attr=htons(attr);
- ah->size=htons(size);
-
- if ( size>0 && data!=NULL ) {
- memcpy(ah->data, data, size);
- }
-
- np->ah=(struct attr_header*)(ah->data+size);
-
-}
-
-
-
-// ----------------------------------------------------------------
-void addPacketEmptyAttr (struct ng_packet *np, unsigned short attr) {
- addPacketAttr(np, attr, 0, NULL);
-}
-
-
-
-// -------------------------------------------------------------------------
-void addPacketByteAttr (struct ng_packet *np, unsigned short attr, char val) {
- addPacketAttr(np, attr, 1, &val);
-}
-
-
-
-// ---------------------------------------------------------------------------
-void addPacketShortAttr (struct ng_packet *np, unsigned short attr, short val) {
-
- short s=htons(val);
-
-
- addPacketAttr(np, attr, 2, &s);
-
-}
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <string.h>
+#include <errno.h>
-
-
-// ------------------------------------------------
-int getPacketTotalSize (const struct ng_packet *np) {
- return ((char*)np->ah)-np->buffer;
-}
-
-
-
-// --------------------------------------------
-struct attr* newEmptyAttr (unsigned short attr) {
- return newAttr(attr, 0, NULL);
-}
-
-
-
-// ------------------------------------------------------------------------
-struct attr* newAttr (unsigned short attr, unsigned short size, void *data) {
-
- struct attr *at;
-
-
- at=malloc(sizeof(struct attr));
- at->attr=attr;
- at->size=size;
- at->data=data;
-
-
- return at;
-
-}
-
-
-
-// ----------------------------------------------------------------
-struct attr* newByteAttr (unsigned short attr, unsigned char value) {
-
- char *v=malloc(sizeof(char));
-
- *v=value;
-
- return newAttr(attr, sizeof(char), v);
-
-}
-
-
-
-// ---------------------------------------------------------
-struct attr* newShortAttr (unsigned short attr, short value) {
-
- short *v=malloc(sizeof(short));
-
- *v=htons(value);
-
- return newAttr(attr, sizeof(short), v);
-
-}
-
-
-
-// -----------------------------------------------------
-struct attr* newIntAttr (unsigned short attr, int value) {
-
- int *v=malloc(sizeof(int));
-
- *v=htonl(value);
-
- return newAttr(attr, sizeof(int), v);
-
-}
-
-
-
-// -----------------------------------------------------------------
-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) {
-
- if ( at!=NULL ) {
- free(at->data);
- free(at);
- }
-
-}
-
-
-
-// --------------------------------------------------------------------------------------------------------------
-int extractPacketAttributes (struct ng_packet *np, unsigned char *error, unsigned short *attr_error, List *attr) {
-
- struct attr *at;
- int ret=0;
-
-
- 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;
- }
-
- at=malloc(sizeof(struct attr));
- at->attr=ntohs(np->ah->attr);
- at->size=ntohs(np->ah->size);
-
- // attribute data bigger than the remaining size: error
- if ( getPacketTotalSize(np)+(int)sizeof(struct attr_header)+at->size>np->maxlen ) {
- free(at);
- ret=-1;
- break;
- }
-
- if ( at->size==0 ) {
- at->data=NULL;
- } else {
- at->data=malloc(at->size*sizeof(char));
- memcpy(at->data, np->ah->data, at->size);
- }
-
- pushBackList(attr, at);
-
- // stop on an END attribute
- if ( at->attr==ATTR_END ) break;
-
- // move to next attribute
- np->ah=(struct attr_header*)(np->ah->data+at->size);
-
- }
-
-
- return ret;
-
-}
+#include "attr.h"
+#include "protocol.h"
-// --------------------------------------------------------------
-void extractSwitchAttributes (struct swi_attr *sa, const List *l) {
-
- const ListNode *ln;
- const struct attr *at;
- int len;
-
-
- memset(sa, 0, sizeof(struct swi_attr));
-
- for (ln=l->first; ln!=NULL; ln=ln->next) {
- at=ln->data;
-
- switch ( at->attr ) {
-
- case ATTR_PRODUCT:
- len=min(at->size, PRODUCT_SIZE);
- memcpy(sa->product, at->data, len);
- trim(sa->product, len);
- break;
-
- case ATTR_NAME:
- len=min(at->size, NAME_SIZE);
- memcpy(sa->name, at->data, len);
- trim(sa->name, len);
- break;
-
- case ATTR_MAC:
- memcpy(&sa->mac, at->data, ETH_ALEN);
- break;
-
- case ATTR_IP:
- sa->nc.ip=*(struct in_addr*)at->data;
- break;
-
- case ATTR_NETMASK:
- sa->nc.netmask=*(struct in_addr*)at->data;
- break;
-
- case ATTR_GATEWAY:
- sa->nc.gw=*(struct in_addr*)at->data;
- break;
-
- case ATTR_DHCP:
- sa->nc.dhcp=( ntohs(*(unsigned short*)at->data)==1 );
- break;
-
- case ATTR_FIRM_VER:
- len=min(at->size, FIRMWARE_SIZE-1);
- memcpy(sa->firmware, at->data, len);
- sa->firmware[len]=0;
- break;
-
- case ATTR_PORTS_COUNT:
- sa->ports=*(unsigned char*)at->data;
- break;
-
- case ATTR_END:
- return;
-
- }
-
- }
-
-
+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;
}
-
#define DEF_PROTOCOL
-#include <stdio.h>
-#include <stdbool.h>
-#include <string.h>
+#include <stdlib.h>
#include <arpa/inet.h>
+
#include <netinet/ether.h>
-#include <ngadmin.h>
#include "list.h"
-#include "lib.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)) ;
+ 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)) ;
+ 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;
+ union {
+ char *buffer;
+ struct ng_header *nh;
+ };
+ int maxlen;
+ struct attr_header *ah;
};
struct attr {
- unsigned short attr;
- unsigned short size;
- void *data;
+ unsigned short attr;
+ unsigned short size;
+ void *data;
};
-
-//
int trim (char *txt, int start);
-//
-int min (int a, int b);
-//
+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);
-//
-void initNgPacket (struct ng_packet *np);
-//
-void addPacketAttr (struct ng_packet *np, unsigned short attr, unsigned short size, void* data);
+static inline void initNgPacket (struct ng_packet *np)
+{
+ np->ah = (struct attr_header*)np->nh->data;
+}
-//
-void addPacketEmptyAttr (struct ng_packet *np, unsigned short attr);
-//
-void addPacketByteAttr (struct ng_packet *np, unsigned short attr, char val);
+void addPacketAttr (struct ng_packet *np, struct attr *at);
-//
-void addPacketShortAttr (struct ng_packet *np, unsigned short attr, short val);
-//
-int getPacketTotalSize (const struct ng_packet *np);
+static inline int getPacketTotalSize (const struct ng_packet *np)
+{
+ return ((char*)np->ah) - np->buffer;
+}
-//
-struct attr* newEmptyAttr (unsigned short attr);
-//
struct attr* newAttr (unsigned short attr, unsigned short size, void *data);
-//
-struct attr* newByteAttr (unsigned short attr, unsigned char value);
-//
-struct attr* newShortAttr (unsigned short attr, short value);
+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);
+}
+
-//
-struct attr* newIntAttr (unsigned short attr, int value);
+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);
+}
-//
-struct attr* newAddrAttr (unsigned short attr, struct in_addr value);
-//
void freeAttr (struct attr *at);
-//
-int extractPacketAttributes (struct ng_packet *np, unsigned char *error, unsigned short *attr_error, List *attr);
-//
-void extractSwitchAttributes (struct swi_attr *sa, const List *l);
+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