From 0eb28539a42fcb01078c7bca793c741317656f14 Mon Sep 17 00:00:00 2001 From: darkcoven Date: Wed, 23 Nov 2011 12:00:00 +0100 Subject: [PATCH] Added support for changing the network configuration. Added very basic support of VLANs, read only. Lib: handling error code on 2 bytes instead of 1. --- cli/commands.c | 184 +++++++++++++++++++++++++++++++++++++++++++-- cli/common.c | 2 +- lib/ngadmin.h | 18 +++++ lib/src/lib.h | 3 + lib/src/network.c | 18 ++--- lib/src/network.h | 2 +- lib/src/ngadmin.c | 158 ++++++++++++++++++++++++++++++++++++-- lib/src/protocol.c | 47 ++++++++---- lib/src/protocol.h | 31 ++++---- 9 files changed, 411 insertions(+), 52 deletions(-) diff --git a/cli/commands.c b/cli/commands.c index c134905..a35b8bf 100644 --- a/cli/commands.c +++ b/cli/commands.c @@ -462,7 +462,7 @@ static bool do_mirror_set (int nb, const char **com, struct ngadmin *nga) { end: free(ports); - return true; + return ret; } @@ -584,6 +584,85 @@ static bool do_name_clear (int nb UNUSED, const char **com UNUSED, struct ngadmi +// ============================================================================= +// netconf + + +static bool do_netconf_set (int nb, const char **com, struct ngadmin *nga) { + + int i, k; + const struct swi_attr *sa; + struct net_conf nc; + bool ret=true; + + + if ( nb==0 ) { + printf("Usage: netconf set [dhcp yes|no] [ip ] [mask ] [gw ]\n"); + return false; + } + + if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) { + printf("must be logged\n"); + return false; + } + + + memset(&nc, 0, sizeof(struct net_conf)); + + for (k=0; k\n"); + printf("Usage: password change \n"); return false; } @@ -1146,6 +1225,102 @@ static bool do_tree (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga +// ============================================================================= +// vlan + + +static char vlan_char (int t) { + + switch ( t ) { + case VLAN_TAGGED: return 'T'; + case VLAN_UNTAGGED: return 'U'; + case VLAN_NO: return ' '; + default: return '?'; + } + +} + + +static bool print_vlan_dot_adv (struct ngadmin *nga) { + + char buffer[512], *b=buffer; + const struct swi_attr *sa; + int i, t; + + + sa=ngadmin_getCurrentSwitch(nga); + + t=sizeof(buffer); + i=ngadmin_getVLANDotConf(nga, buffer, &t); + if ( i!=ERR_OK ) { + printErrCode(i); + return false; + } + + printf("Ports configuration: \n"); + printf("VLAN\t"); + for (i=1; i<=sa->ports; ++i) { + printf("%i\t", i); + } + putchar('\n'); + + while ( b-bufferports; ++i) { + printf("%c\t", vlan_char(*b++)); + } + putchar('\n'); + } + + + return true; + +} + + +static bool do_vlan_show (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) { + + int i, t, ret=true; + + + if ( ngadmin_getCurrentSwitch(nga)==NULL ) { + printf("must be logged\n"); + ret=false; + goto end; + } + + if ( (i=ngadmin_getVLANType(nga, &t))!=ERR_OK ) { + printErrCode(i); + ret=false; + goto end; + } + + + printf("VLAN type: "); + switch ( t ) { + case VLAN_DISABLED: printf("disabled\n"); break; + case VLAN_PORT_BASIC: printf("port basic\n"); break; + case VLAN_PORT_ADV: printf("port advanced\n"); break; + case VLAN_DOT_BASIC: printf("802.1Q basic\n"); break; + + case VLAN_DOT_ADV: + printf("802.1Q advanced\n\n"); + ret=print_vlan_dot_adv(nga); + break; + + default: printf("unknown (%i)\n", t); + } + + + + end: + + return ret; + +} + + + // ============================================================================= @@ -1187,8 +1362,7 @@ COM_ROOT_START(coms) COM_END COM_START(netconf) - COM_TERM(show, NULL, false) - COM_TERM(set, NULL, true) + COM_TERM(set, do_netconf_set, true) COM_END COM_START(password) @@ -1226,7 +1400,7 @@ COM_ROOT_START(coms) COM_TERM(tree, do_tree, false) COM_START(vlan) - COM_TERM(show, NULL, false) + COM_TERM(show, do_vlan_show, false) COM_TERM(mode, NULL, true) COM_END diff --git a/cli/common.c b/cli/common.c index ab8bdbb..59f7058 100644 --- a/cli/common.c +++ b/cli/common.c @@ -93,7 +93,7 @@ void displaySwitchTab (const struct swi_attr *sa, int nb) { } - printf("Num\tMac\t\t\tProduct\t\tName\t\t\tIP/mask\t\t\t\tDHCP\tPorts\tFirmware\n"); + printf("Num\tMac\t\t\tProduct\t\tName\t\t\tIP/mask\t\t\tDHCP\tPorts\tFirmware\n"); for (i=0; isock, SOL_SOCKET, SO_BINDTODEVICE, nga->iface, strlen(nga->iface)+1))<0 ) { perror("setsockopt(SO_BINDTODEVICE)"); return ret; @@ -172,8 +170,8 @@ int sendNgPacket (struct ngadmin *nga, char code, const List *attr) { -// --------------------------------------------------------------------------------------------------- -int recvNgPacket (struct ngadmin *nga, char code, char *error, unsigned short *attr_error, List *attr) { +// ------------------------------------------------------------------------------------------------------------- +int recvNgPacket (struct ngadmin *nga, char code, unsigned short *error, unsigned short *attr_error, List *attr) { char buffer[1500]; struct ng_packet np; @@ -217,8 +215,7 @@ int recvNgPacket (struct ngadmin *nga, char code, char *error, unsigned short *a int readRequest (struct ngadmin *nga, List *attr) { int i, ret=ERR_OK; - unsigned short attr_error; - char err; + unsigned short err, attr_error; if ( nga==NULL ) { @@ -238,7 +235,7 @@ int readRequest (struct ngadmin *nga, List *attr) { ret=ERR_NET; } - if ( err==7 && attr_error==ATTR_PASSWORD ) { + if ( err==0x0700 && attr_error==ATTR_PASSWORD ) { ret=ERR_BADPASS; goto end; } @@ -257,8 +254,7 @@ int readRequest (struct ngadmin *nga, List *attr) { int writeRequest (struct ngadmin *nga, List *attr) { int i, ret=ERR_OK; - unsigned short attr_error; - char err; + unsigned short err, attr_error; if ( nga==NULL ) { @@ -291,11 +287,13 @@ int writeRequest (struct ngadmin *nga, List *attr) { goto end; } - if ( err==7 && attr_error==ATTR_PASSWORD ) { + if ( err==0x0700 && attr_error==ATTR_PASSWORD ) { ret=ERR_BADPASS; goto end; } + // err==0x0500 + end: // the switch replies to write request by just a header (no attributes), so the list can be destroyed diff --git a/lib/src/network.h b/lib/src/network.h index a51992e..c9043d2 100644 --- a/lib/src/network.h +++ b/lib/src/network.h @@ -32,7 +32,7 @@ int updateTimeout (struct ngadmin *nga); int sendNgPacket (struct ngadmin *nga, char code, const List *attr); // -int recvNgPacket (struct ngadmin *nga, char code, char *error, unsigned short *attr_error, List *attr); +int recvNgPacket (struct ngadmin *nga, char code, unsigned short *error, unsigned short *attr_error, List *attr); // int readRequest (struct ngadmin *nga, List *attr); diff --git a/lib/src/ngadmin.c b/lib/src/ngadmin.c index d1e33d1..1f32d09 100644 --- a/lib/src/ngadmin.c +++ b/lib/src/ngadmin.c @@ -589,7 +589,11 @@ int ngadmin_getBitrateLimits (struct ngadmin *nga, int *ports) { List *attr; ListNode *ln; struct attr *at; - int ret=ERR_OK, i; + int ret=ERR_OK; + struct { + char port; + int bitrate; + } __attribute__((packed)) *p; if ( nga==NULL || ports==NULL ) { @@ -609,10 +613,12 @@ int ngadmin_getBitrateLimits (struct ngadmin *nga, int *ports) { for (ln=attr->first; ln!=NULL; ln=ln->next) { at=ln->data; - if ( at->attr==ATTR_BITRATE_INPUT && at->size>=5 && (i=*(char*)(at->data)-1)>=0 && icurrent->ports ) { - ports[i*2+0]=ntohl(*(int*)(1+(char*)at->data)); - } else if ( at->attr==ATTR_BITRATE_OUTPUT && at->size>=5 && (i=*(char*)(at->data)-1)>=0 && icurrent->ports ) { - ports[i*2+1]=ntohl(*(int*)(1+(char*)at->data)); + p=at->data; + if ( at->sizeport<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); } } @@ -872,7 +878,7 @@ int ngadmin_getMirror (struct ngadmin *nga, char *ports) { for (ln=attr->first; ln!=NULL; ln=ln->next) { at=ln->data; p=at->data; - if ( at->attr==ATTR_MIRROR && at->size>=2+sa->ports/8 && p[0]<=nga->current->ports ) { + 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]>>(sa->ports-i))&1; @@ -1118,3 +1124,143 @@ int ngadmin_cabletest (struct ngadmin *nga, struct cabletest *ct, int nb) { +// -------------------------------------------------------------------- +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)); + 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; + } + + + if ( nc->dhcp ) { + sa->nc.dhcp=true; + } else { + memcpy(&sa->nc, nc, sizeof(struct net_conf)); + } + + + 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_getVLANDotConf (struct ngadmin *nga, char *buf, int *len) { + + List *attr; + ListNode *ln; + struct attr *at; + struct swi_attr *sa; + int ret=ERR_OK, i; + char *b=buf, *p=NULL; + + + if ( nga==NULL || buf==NULL || len==NULL || *len<=0 ) { + return ERR_INVARG; + } else if ( (sa=nga->current)==NULL ) { + return ERR_NOTLOG; + } + + + 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 ( (b-buf)+2+sa->ports>*len ) break; // no more room + if ( at->attr==ATTR_VLAN_DOT_CONF && at->size>=4 ) { + *(unsigned short*)b=ntohs(*(unsigned short*)p);b+=2; + for (i=1; i<=sa->ports; ++i) { + if ( (p[3]>>(sa->ports-i))&1 ) *b++=VLAN_TAGGED; // tagged + else if ( (p[2]>>(sa->ports-i))&1 ) *b++=VLAN_UNTAGGED; // untagged + else *b++=VLAN_NO; + } + } + } + + *len=b-buf; + + + end: + destroyList(attr, (void(*)(void*))freeAttr); + + return ret; + +} + + + + + diff --git a/lib/src/protocol.c b/lib/src/protocol.c index a71df2e..a342c96 100644 --- a/lib/src/protocol.c +++ b/lib/src/protocol.c @@ -50,11 +50,7 @@ bool validateNgHeader (const struct ng_header *nh, char code, const struct ether return false; } - if ( nh->unk2!=0 ) { - return false; - } - - if ( *(unsigned short*)nh->unk3!=0 ) { + if ( *(unsigned short*)nh->unk2!=0 ) { return false; } @@ -70,7 +66,7 @@ bool validateNgHeader (const struct ng_header *nh, char code, const struct ether return false; } - if ( *(unsigned int*)nh->unk4!=0 ) { + if ( *(unsigned int*)nh->unk3!=0 ) { return false; } @@ -184,6 +180,19 @@ struct attr* newByteAttr (unsigned short attr, unsigned char value) { +// --------------------------------------------------------- +struct attr* newShortAttr (unsigned short attr, short value) { + + short *v=malloc(sizeof(short)); + + *v=value; + + return newAttr(attr, sizeof(short), v); + +} + + + // ----------------------------------------------------- struct attr* newIntAttr (unsigned short attr, int value) { @@ -197,6 +206,19 @@ struct attr* newIntAttr (unsigned short attr, int value) { +// ----------------------------------------------------------------- +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) { @@ -209,19 +231,14 @@ void freeAttr (struct attr *at) { -// ----------------------------------------------------------------------------------------------------- -void extractPacketAttributes (struct ng_packet *np, char *error, unsigned short *attr_error, List *attr) { +// --------------------------------------------------------------------------------------------------------------- +void extractPacketAttributes (struct ng_packet *np, unsigned short *error, unsigned short *attr_error, List *attr) { struct attr *at; - if ( error!=NULL ) { - *error=np->nh->error; - } - - if ( attr_error!=NULL ) { - *attr_error=ntohs(np->nh->attr); - } + if ( error!=NULL ) *error=ntohs(np->nh->error); + if ( attr_error!=NULL ) *attr_error=ntohs(np->nh->attr); while ( getPacketTotalSize(np)maxlen ) { diff --git a/lib/src/protocol.h b/lib/src/protocol.h index 4b4407b..3b26f1d 100644 --- a/lib/src/protocol.h +++ b/lib/src/protocol.h @@ -18,17 +18,16 @@ struct ng_header { - char unk1; // always 1 - char code; - char error; - char unk2; // always 0 - unsigned short attr; // attribute code which caused error - char unk3[2]; // always 0 - char client_mac[ETH_ALEN]; - char switch_mac[ETH_ALEN]; - unsigned int seqnum; - char proto_id[4]; // always "NSDP" - char unk4[4]; // always 0 + char unk1; // always 1, maybe version + char code; // request code: read request, read reply, write request, write reply + unsigned short error; // error code, 0 when no error + 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)) ; @@ -57,8 +56,6 @@ struct attr { -extern const unsigned short helloRequest[]; - extern const struct ether_addr nullMac; @@ -99,14 +96,20 @@ 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); + // struct attr* newIntAttr (unsigned short attr, int value); +// +struct attr* newAddrAttr (unsigned short attr, struct in_addr value); + // void freeAttr (struct attr *at); // -void extractPacketAttributes (struct ng_packet *np, char *error, unsigned short *attr_error, List *attr); +void extractPacketAttributes (struct ng_packet *np, unsigned short *error, unsigned short *attr_error, List *attr); // void extractSwitchAttributes (struct swi_attr *sa, const List *l); -- 2.39.2